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

  
    <entry>
      <title>Python vs C++: Selecting the Right Tool for the Job</title>
      <id>https://realpython.com/python-vs-cpp/</id>
      <link href="https://realpython.com/python-vs-cpp/"/>
      <updated>2019-09-11T14:00:00+00:00</updated>
      <summary>In this intermediate-level article, you&#39;ll explore the similarities and differences you&#39;ll find when comparing Python vs C++. You&#39;ll learn about memory management, virtual machines, object-oriented programming differences, and much more!</summary>
      <content type="html">
        &lt;p&gt;Are you a C++ developer comparing Python vs C++? Are you looking at Python and wondering what all the fuss is about? Do you wonder how Python compares to the concepts you already know? Or perhaps you have a bet on who would win if you locked C++ and Python in a cage and let them battle it out? Then this article is for you!&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;Differences and similarities when you&amp;rsquo;re comparing Python vs C++&lt;/li&gt;
&lt;li&gt;Times when Python might be a better choice for a problem and vice versa&lt;/li&gt;
&lt;li&gt;Resources to turn to as you have questions while learning Python&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article is aimed at C++ developers who are learning Python. It assumes a basic knowledge of both languages and will use concepts from Python 3.6 and up, as well as C++11 or later.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s dive into looking at Python vs C++!&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;comparing-languages-python-vs-c&quot;&gt;Comparing Languages: Python vs C++&lt;/h2&gt;
&lt;p&gt;Frequently, you&amp;rsquo;ll find articles that extoll the virtues of one programming language over another. Quite often, they devolve into efforts to promote one language by degrading the other. This isn&amp;rsquo;t that type of article.  &lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re comparing Python vs C++, remember that they&amp;rsquo;re both tools, and they both have uses for different problems. Think about comparing a hammer and a screwdriver. You &lt;em&gt;could&lt;/em&gt; use a screwdriver to drive in nails, and you &lt;em&gt;could&lt;/em&gt; use a hammer to force in screws, but neither experience will be all that effective.&lt;/p&gt;
&lt;p&gt;Using the right tool for the job is important. In this article, you&amp;rsquo;ll learn about the features of Python and C++ that make each of them the right choice for certain types of problems. So, don&amp;rsquo;t view the &amp;ldquo;vs&amp;rdquo; in Python vs C++ as meaning &amp;ldquo;against.&amp;rdquo; Rather, think of it as a comparison.&lt;/p&gt;
&lt;h2 id=&quot;compilation-vs-virtual-machine&quot;&gt;Compilation vs Virtual Machine&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start with the biggest difference when you&amp;rsquo;re comparing Python vs C++. In C++, you use a compiler that converts your source code into machine code and produces an executable. The executable is a separate file that can then be run as a stand-alone program:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/cpp_single_compile.209a9e10bff5.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/cpp_single_compile.209a9e10bff5.png&quot; width=&quot;1233&quot; height=&quot;303&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_single_compile.209a9e10bff5.png&amp;amp;w=308&amp;amp;sig=5f6e74cc693b578b1f13ce0b7714754f4546f349 308w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_single_compile.209a9e10bff5.png&amp;amp;w=616&amp;amp;sig=bacc781219de00d704d49dced7fa4c1acf567467 616w, https://files.realpython.com/media/cpp_single_compile.209a9e10bff5.png 1233w&quot; sizes=&quot;75vw&quot; alt=&quot;Compiling a C++ program for windows.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This process outputs actual machine instructions for the specific processor and operating system it&amp;rsquo;s built for. In this drawing, it&amp;rsquo;s a Windows program. This means you&amp;rsquo;d have to recompile your program separately for Windows, Mac, and Linux:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/cpp_multi_compile.3ff938bd23f1.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/cpp_multi_compile.3ff938bd23f1.png&quot; width=&quot;1236&quot; height=&quot;1086&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_multi_compile.3ff938bd23f1.png&amp;amp;w=309&amp;amp;sig=ba5cbdd3e8ee6971378fa18fa2cf5b00e03a991e 309w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_multi_compile.3ff938bd23f1.png&amp;amp;w=618&amp;amp;sig=6f3032c9725c0562bafc2db81f49d43c276617e6 618w, https://files.realpython.com/media/cpp_multi_compile.3ff938bd23f1.png 1236w&quot; sizes=&quot;75vw&quot; alt=&quot;Compiling a C++ program on three operating systems.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll likely need to modify your C++ code to run on those different systems as well.&lt;/p&gt;
&lt;p&gt;Python, on the other hand, uses a different process. Now, remember that you&amp;rsquo;ll be looking at &lt;code&gt;CPython&lt;/code&gt; which is the standard implementation for the language. Unless you&amp;rsquo;re doing something special, this is the Python you&amp;rsquo;re running.&lt;/p&gt;
&lt;p&gt;Python runs each time you execute your program. It compiles your source just like the C++ compiler. The difference is that Python compiles to &lt;a href=&quot;https://docs.python.org/3/glossary.html#term-bytecode&quot;&gt;bytecode&lt;/a&gt; instead of native machine code. Bytecode is the native instruction code for the &lt;a href=&quot;https://leanpub.com/insidethepythonvirtualmachine/read&quot;&gt;Python virtual machine&lt;/a&gt;. To speed up subsequent runs of your program, Python stores the bytecode in &lt;code&gt;.pyc&lt;/code&gt; files:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/python_compile_to_pyc.514448b58d8a.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/python_compile_to_pyc.514448b58d8a.png&quot; width=&quot;1233&quot; height=&quot;303&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/python_compile_to_pyc.514448b58d8a.png&amp;amp;w=308&amp;amp;sig=01c3bdf0f690227766c03351343ed54ec5a68137 308w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/python_compile_to_pyc.514448b58d8a.png&amp;amp;w=616&amp;amp;sig=9cc2117cb8807e500fbcda4898e09cc7ebdeff59 616w, https://files.realpython.com/media/python_compile_to_pyc.514448b58d8a.png 1233w&quot; sizes=&quot;75vw&quot; alt=&quot;Python compiles a py file into a pyc file.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using Python 2, then you&amp;rsquo;ll find these files next to the &lt;code&gt;.py&lt;/code&gt; files. For Python 3, you&amp;rsquo;ll find them in a &lt;code&gt;__pycache__&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;The generated bytecode doesn&amp;rsquo;t run natively on your processor. Instead, it&amp;rsquo;s run by the Python virtual machine. This is similar to the Java virtual machine or the .NET Common Runtime Environment. The initial run of your code will result in a compilation step. Then, the bytecode will be interpreted to run on your specific hardware:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/python_initial_run.7d67c05e0bc2.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/python_initial_run.7d67c05e0bc2.png&quot; width=&quot;1833&quot; height=&quot;303&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/python_initial_run.7d67c05e0bc2.png&amp;amp;w=458&amp;amp;sig=5b7ebaf8c06347236c6b8782e15825fd50922466 458w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/python_initial_run.7d67c05e0bc2.png&amp;amp;w=916&amp;amp;sig=746bafe3348367b13562e7c7dc9ca1812212b937 916w, https://files.realpython.com/media/python_initial_run.7d67c05e0bc2.png 1833w&quot; sizes=&quot;75vw&quot; alt=&quot;Python compiles a py file into a pyc file and then executes it.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As long as the program hasn&amp;rsquo;t been changed, each subsequent run will skip the compilation step and use the previously compiled bytecode to interpret: &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/python_execute.pyc.f20350ccc1cf.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/python_execute.pyc.f20350ccc1cf.png&quot; width=&quot;843&quot; height=&quot;303&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/python_execute.pyc.f20350ccc1cf.png&amp;amp;w=210&amp;amp;sig=eeda5bcba2735211d811a5223fa1ab6d7c2d7921 210w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/python_execute.pyc.f20350ccc1cf.png&amp;amp;w=421&amp;amp;sig=3d27ddf337bbc98e999e89aa109b01334260b004 421w, https://files.realpython.com/media/python_execute.pyc.f20350ccc1cf.png 843w&quot; sizes=&quot;75vw&quot; alt=&quot;Python executes a pyc file.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Interpreting code is going to be slower than running native code directly on the hardware. So why does Python work that way? Well, interpreting the code in a virtual machine means that only the virtual machine needs to be compiled for a specific operating system on a specific processor. All of the Python code it runs will run on any machine that has Python. &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; CPython is written in C, so it can run on most systems that have a C compiler.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Another feature of this cross-platform support is that Python&amp;rsquo;s extensive standard library is written to work on all operating systems. &lt;/p&gt;
&lt;p&gt;Using &lt;a href=&quot;https://docs.python.org/3.7/library/pathlib.html&quot;&gt;&lt;code&gt;pathlib&lt;/code&gt;&lt;/a&gt;, for example, will manage path separators for you whether you&amp;rsquo;re on Windows, Mac, or Linux. The developers of those libraries spent a lot of time making it portable so you don&amp;rsquo;t need to worry about it in your Python program!&lt;/p&gt;
&lt;p&gt;Before you move on, let&amp;rsquo;s start keeping track of a Python vs C++ comparison chart. As you cover new comparisons, they&amp;rsquo;ll be added in italics:&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;Feature&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Faster Execution&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Cross-Platform Execution&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Now that you&amp;rsquo;ve seen the differences in run time when you&amp;rsquo;re comparing Python vs C++, let&amp;rsquo;s dig into the specifics of the languages&amp;rsquo; syntax.&lt;/p&gt;
&lt;h2 id=&quot;syntax-differences&quot;&gt;Syntax Differences&lt;/h2&gt;
&lt;p&gt;Python and C++ share many syntactical similarities, but there are a few areas worth discussing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Whitespace&lt;/li&gt;
&lt;li&gt;Boolean expressions&lt;/li&gt;
&lt;li&gt;Variables and pointers&lt;/li&gt;
&lt;li&gt;Comprehensions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s start with the most contentious one first: whitespace.&lt;/p&gt;
&lt;h3 id=&quot;whitespace&quot;&gt;Whitespace&lt;/h3&gt;
&lt;p&gt;The first thing most developers notice when comparing Python vs C++ is the &amp;ldquo;whitespace issue.&amp;rdquo; Python uses leading whitespace to mark scope. This means that the body of an &lt;code&gt;if&lt;/code&gt; block or other similar structure is indicated by the level of indentation. C++ uses curly braces (&lt;code&gt;{}&lt;/code&gt;) to indicate the same idea.&lt;/p&gt;
&lt;p&gt;While the Python lexer will accept any whitespace as long as you&amp;rsquo;re consistent, &lt;a href=&quot;https://realpython.com/python-pep8/&quot;&gt;PEP8&lt;/a&gt; (the &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot;&gt;official style guide&lt;/a&gt; for Python) specifies 4 spaces for each level of indentation. Most editors can be configured to do this automatically.&lt;/p&gt;
&lt;p&gt;There has been an enormous amount of &lt;a href=&quot;https://unspecified.wordpress.com/2011/10/18/why-pythons-whitespace-rule-is-right/&quot;&gt;writing&lt;/a&gt;, &lt;a href=&quot;https://www.quora.com/Do-you-think-that-indentation-in-Python-is-annoying&quot;&gt;shouting&lt;/a&gt;, and &lt;a href=&quot;https://news.ycombinator.com/item?id=5231632&quot;&gt;ranting&lt;/a&gt; about Python&amp;rsquo;s whitespace rules already, so let&amp;rsquo;s just jump past that issue and on to other matters.&lt;/p&gt;
&lt;p&gt;Instead of relying on a lexical marker like &lt;code&gt;;&lt;/code&gt; to end each statement, Python uses the end of the line. If you need to extend a statement over a single line, then you can use the backslash (&lt;code&gt;\&lt;/code&gt;) to indicate that. (Note that if you&amp;rsquo;re inside a set of parentheses, then the continuation character is not needed.)&lt;/p&gt;
&lt;p&gt;There are people who are unhappy on both sides of the whitespace issue. Some Python developers love that you don&amp;rsquo;t have to type out braces and semicolons. Some C++ developers hate the reliance on formatting. Learning to be comfortable with both is your best bet.&lt;/p&gt;
&lt;p&gt;Now that you&amp;rsquo;ve looked at the whitespace issue, let&amp;rsquo;s move on to one that&amp;rsquo;s a bit less contentious: Boolean expressions.&lt;/p&gt;
&lt;h3 id=&quot;boolean-expressions&quot;&gt;Boolean Expressions&lt;/h3&gt;
&lt;p&gt;The way you&amp;rsquo;ll use &lt;a href=&quot;https://realpython.com/python-data-types/#boolean-type-boolean-context-and-truthiness&quot;&gt;Boolean expressions&lt;/a&gt; changes slightly in Python vs C++. In C++, you can use numeric values to indicate &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;, in addition to the built-in values. Anything that evaluates to &lt;code&gt;0&lt;/code&gt; is considered &lt;code&gt;false&lt;/code&gt;, while every other numeric value is &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Python has a similar concept but extends it to include other cases. The basics are quite similar. The &lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#truth-value-testing&quot;&gt;Python documentation&lt;/a&gt; states that the following items evaluate to &lt;code&gt;False&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Constants defined as false:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;None&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;False&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Zeros of any numeric type:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0.0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0j&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Decimal(0)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Fraction(0, 1)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Empty sequences and collections:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#39;&#39;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;set()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;range(0)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All other items are &lt;code&gt;True&lt;/code&gt;. This means that an empty list &lt;code&gt;[]&lt;/code&gt; is &lt;code&gt;False&lt;/code&gt;, while a list containing only zero &lt;code&gt;[0]&lt;/code&gt; is still &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Most objects will evaluate to &lt;code&gt;True&lt;/code&gt;, unless the object has &lt;code&gt;__bool__()&lt;/code&gt; which returns &lt;code&gt;False&lt;/code&gt; or &lt;code&gt;__len__()&lt;/code&gt; which returns 0. This allows you to extend your custom classes to act as Boolean expressions.&lt;/p&gt;
&lt;p&gt;Python has a few slight changes from C++ in the Boolean operators as well. For starters, &lt;code&gt;if&lt;/code&gt; and &lt;code&gt;while&lt;/code&gt; statements do not require the surrounding parentheses as they do in C++. Parentheses can aid in readability, however, so use your best judgment.&lt;/p&gt;
&lt;p&gt;Most C++ Boolean operators have similar operators in Python:&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;C++ Operator&lt;/th&gt;
&lt;th&gt;Python Operator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;and&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;||&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;or&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;not&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;|&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;|&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Most of the operators are similar to C++, but if you want to brush up you can read &lt;a href=&quot;https://realpython.com/python-operators-expressions/&quot;&gt;Operators and Expressions in Python&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;variables-and-pointers&quot;&gt;Variables and Pointers&lt;/h3&gt;
&lt;p&gt;When you first start using Python after writing in C++, you might not give variables much thought. They seem to generally work as they do in C++. However, they&amp;rsquo;re not the same. Whereas in C++ you use variables to reference values, in Python you use names.&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 this section, where you&amp;rsquo;re looking at variables and names in Python vs C++, you&amp;rsquo;ll use &lt;strong&gt;variables&lt;/strong&gt; for C++ and &lt;strong&gt;names&lt;/strong&gt; for Python. Elsewhere, they will both be called &lt;strong&gt;variables&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;First, let&amp;rsquo;s back up a bit and take a broader look at Python&amp;rsquo;s &lt;a href=&quot;https://docs.python.org/3.6/reference/datamodel.html&quot;&gt;object model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In Python, &lt;em&gt;everything&lt;/em&gt; is an object. Numbers are held in objects. Modules are held in objects. Both the object of a class &lt;em&gt;and&lt;/em&gt; the class itself are objects. Functions are also objects:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_list_object&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_list_object&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class_object&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class_object&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;class &amp;#39;list&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sayHi&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;gp&quot;&gt;... &lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{name}&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;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;a_function_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sayHi&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_function_object&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;function sayHi at 0x7faa326ac048&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Calling &lt;code&gt;list()&lt;/code&gt; creates a new list object, which you assign to &lt;code&gt;a_list_object&lt;/code&gt;. Using the name of the class &lt;code&gt;list&lt;/code&gt; by itself places a label on the class object. You can place a new label on a function as well. This is a powerful tool and, like all powerful tools, it can be dangerous. (I&amp;rsquo;m looking at you, Mr. Chainsaw.)&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 code above is shown running in a &lt;a href=&quot;https://realpython.com/interacting-with-python/&quot;&gt;REPL&lt;/a&gt;, which stands for &amp;ldquo;Read, Eval, Print Loop.&amp;rdquo; This interactive environment is used frequently to try out ideas in Python and other interpreted languages. &lt;/p&gt;
&lt;p&gt;If you type &lt;code&gt;python&lt;/code&gt; at a command prompt, then it will bring up a REPL where you can start typing in code and trying things out for yourself!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Moving back to the Python vs C++ discussion, note that this is behavior is different from what you&amp;rsquo;ll see in C++. Unlike Python, C++ has variables that are assigned to a memory location, and you must indicate how much memory that variable will use:&lt;/p&gt;
&lt;div class=&quot;highlight cpp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an_int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_big_array_of_floats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REALLY_BIG_NUMBER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Python, all objects are created in memory, and you apply labels to them. The labels themselves don&amp;rsquo;t have types, and they can be put on any type of object:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_flexible_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_flexible_name&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_flexible_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;This is a string&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_flexible_name&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;This is a string&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_flexible_name&lt;/span&gt; &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;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;more info&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.26&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_flexible_name&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[3, &amp;#39;more info&amp;#39;, 3.26]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_flexible_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_flexible_name&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;built-in function print&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can assign &lt;code&gt;my_flexible_name&lt;/code&gt; to any type of object, and Python will just roll with it.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re comparing Python vs C++, the difference in variables vs names can be a bit confusing, but it comes with some excellent benefits. One is that in Python you don&amp;rsquo;t have &lt;a href=&quot;https://realpython.com/pointers-in-python/&quot;&gt;pointers&lt;/a&gt;, and you never need to think about heap vs stack issues. You&amp;rsquo;ll dive into memory management a bit later in this article.&lt;/p&gt;
&lt;h3 id=&quot;comprehensions&quot;&gt;Comprehensions&lt;/h3&gt;
&lt;p&gt;Python has a language feature called &lt;a href=&quot;https://realpython.com/courses/using-list-comprehensions-effectively/&quot;&gt;&lt;strong&gt;list comprehensions&lt;/strong&gt;&lt;/a&gt;. While it&amp;rsquo;s possible to emulate list comprehensions in C++, it&amp;rsquo;s fairly tricky. In Python, they&amp;rsquo;re a basic tool that&amp;rsquo;s taught to beginning programmers.  &lt;/p&gt;
&lt;p&gt;One way of thinking about list comprehensions is that they&amp;rsquo;re like a super-charged initializer for lists, dicts, or sets. Given one iterable object, you can create a list, and filter or modify the original as you do so:&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;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;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;go&quot;&gt;[0, 1, 4, 9, 16]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This script starts with the iterable &lt;code&gt;range(5)&lt;/code&gt; and creates a list that contains the square for each item in the iterable.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s possible to add conditions to the values in the first iterable:&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;odd_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;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;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;if&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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;odd_squares&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 9]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;if x % 2&lt;/code&gt; at the end of this comprehension limits the numbers used from &lt;code&gt;range(5)&lt;/code&gt; to only the odd ones.&lt;/p&gt;
&lt;p&gt;At this point you might be having two thoughts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;That&amp;rsquo;s a powerful syntax trick that will simplify some parts of my code.&lt;/li&gt;
&lt;li&gt;You can do the same thing in C++.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;While it&amp;rsquo;s true that you can create a &lt;code&gt;vector&lt;/code&gt; of the squares of the odd numbers in C++, doing so usually means a little more code:&lt;/p&gt;
&lt;div class=&quot;highlight cpp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;odd_squares&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ii&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ii&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&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;ii&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ii&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;odd_squares&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ii&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;For developers coming from C-style languages, list comprehensions are one of the first noticeable ways they can &lt;a href=&quot;https://realpython.com/learning-paths/writing-pythonic-code/&quot;&gt;write more Pythonic code&lt;/a&gt;. Many developers start writing Python with C++ structure:&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;odd_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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ii&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ii&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;odd_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;ii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is perfectly valid Python. It will likely run more slowly, however, and it&amp;rsquo;s not as clear and concise as the list comprehension. Learning to use list comprehensions will not only speed up your code, but it will also make your code more Pythonic and easier to read!&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 you&amp;rsquo;re reading about Python, you&amp;rsquo;ll frequently see the word &lt;strong&gt;Pythonic&lt;/strong&gt; used to describe something. This is just a term the community uses to describe code that is clean, elegant and looks like it was written by a Python Jedi.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;pythons-stdalgorithms&quot;&gt;Python&amp;rsquo;s &lt;code&gt;std::algorithms&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;C++ has a rich set of algorithms built into the standard library. Python has a similar set of built-in functions that cover the same ground.&lt;/p&gt;
&lt;p&gt;The first and most powerful of these is the &lt;a href=&quot;https://www.pythoncentral.io/quick-tip-using-pythons-in-operator/&quot;&gt;&lt;code&gt;in&lt;/code&gt; operator&lt;/a&gt;, which provides a quite readable test to see if an item is included in a &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;list&lt;/a&gt;, &lt;a href=&quot;https://realpython.com/python-sets/&quot;&gt;set&lt;/a&gt;, or &lt;a href=&quot;https://realpython.com/courses/dictionaries-python/&quot;&gt;dictionary&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;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;193&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;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;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Jim&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;gray&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Zoe&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blond&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;David&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;brown&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Jim&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Fred&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;gray&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that the &lt;code&gt;in&lt;/code&gt; operator, when used on dictionaries, only tests for keys, not values. This is shown by the final test, &lt;code&gt;&#39;gray&#39; in y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;in&lt;/code&gt; can be combined with &lt;code&gt;not&lt;/code&gt; for quite readable 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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&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;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{name}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; not found&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next up in your parade of Python built-in operators is &lt;a href=&quot;https://docs.python.org/3.7/library/functions.html?any#any&quot;&gt;&lt;code&gt;any&lt;/code&gt;&lt;/a&gt;. This is a boolean function that returns &lt;code&gt;True&lt;/code&gt; if any element of the given iterable evaluates to &lt;code&gt;True&lt;/code&gt;. This can seem a little silly until you remember your list comprehensions! Combining these two can produce powerful, clear syntax for many situations:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_big_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;875&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_small_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&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;any&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_big_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;any&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_small_list&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;Finally, you have &lt;a href=&quot;https://docs.python.org/3.7/library/functions.html?all#all&quot;&gt;&lt;code&gt;all&lt;/code&gt;&lt;/a&gt;, which is similar to &lt;code&gt;any&lt;/code&gt;. This returns &lt;code&gt;True&lt;/code&gt; &lt;em&gt;only&lt;/em&gt; if&amp;mdash;you guessed it&amp;mdash;&lt;em&gt;all&lt;/em&gt; of the elements in the iterable are &lt;code&gt;True&lt;/code&gt;. Again, combining this with list comprehensions produces a powerful language feature:&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;list_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;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;list_b&lt;/span&gt; &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;3&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;nb&quot;&gt;all&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;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;all&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;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_b&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;&lt;code&gt;any&lt;/code&gt; and &lt;code&gt;all&lt;/code&gt; can cover much of the same ground where C++ developers would look to &lt;code&gt;std::find&lt;/code&gt; or &lt;code&gt;std::find_if&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; In the &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;all&lt;/code&gt; examples above, you can remove the brackets (&lt;code&gt;[]&lt;/code&gt;) without any loss of functionality. (for example: &lt;code&gt;all(x % 2 for x in list_a)&lt;/code&gt;) This makes use of &lt;a href=&quot;https://realpython.com/introduction-to-python-generators/&quot;&gt;generator expressions&lt;/a&gt; which, while quite handy, are beyond the scope of this article.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Before moving on to variable typing, let&amp;rsquo;s update your Python vs C++ comparison chart:&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;Feature&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Faster Execution&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-Platform Execution&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Single-Type Variables&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Multiple-Type Variables&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Comprehensions&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Rich Set of Built-In Algorithms&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Okay, now you&amp;rsquo;re ready to look at variable and parameter typing. Let&amp;rsquo;s go!&lt;/p&gt;
&lt;h2 id=&quot;static-vs-dynamic-typing&quot;&gt;Static vs Dynamic Typing&lt;/h2&gt;
&lt;p&gt;Another large topic when you&amp;rsquo;re comparing Python vs C++ is the use of data types. C++ is a statically typed language, while Python is dynamically typed. Let&amp;rsquo;s explore what that means.&lt;/p&gt;
&lt;h3 id=&quot;static-typing&quot;&gt;Static Typing&lt;/h3&gt;
&lt;p&gt;C++ is statically typed, which means that each variable you use in your code must have a specific data type like &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;char&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, and so forth. You can only assign values of the correct type to a variable, unless you jump through some hoops.&lt;/p&gt;
&lt;p&gt;This has some advantages for both the developer and the compiler. The developer gains the advantage of knowing what the type of a particular variable is ahead of time, and therefore which operations are allowed. The compiler can use the type information to optimize the code, making it smaller, faster, or both.&lt;/p&gt;
&lt;p&gt;This advance knowledge comes at a cost, however. The parameters passed into a function must match the type expected by the function, which can reduce the flexibility and potential usefulness of the code.&lt;/p&gt;
&lt;h3 id=&quot;duck-typing&quot;&gt;Duck Typing&lt;/h3&gt;
&lt;p&gt;Dynamic typing is frequently referred to as &lt;strong&gt;duck typing.&lt;/strong&gt; It&amp;rsquo;s an odd name, and you&amp;rsquo;ll read more about that in just a minute! But first, let&amp;rsquo;s start with an example. This function takes a file object and reads the first ten lines:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_ten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_like_object&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;line_number&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;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_like_object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{line_number}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; = {x.strip()}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To use this function, you&amp;rsquo;ll create a file object and pass it in:&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;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;types.py&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;read_ten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This shows how the basic design of the function works. While this function was described as &amp;ldquo;reading the first ten lines from a file object,&amp;rdquo; there is nothing in Python that requires that &lt;code&gt;file_like_object&lt;/code&gt; &lt;em&gt;be&lt;/em&gt; a file. As long as the object passed in supports &lt;code&gt;.readline()&lt;/code&gt;, the object can be of any type:&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;Duck&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;readline&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;s2&quot;&gt;&amp;quot;quack&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_duck&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;read_ten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_duck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Calling &lt;code&gt;read_ten()&lt;/code&gt; with a &lt;code&gt;Duck&lt;/code&gt; object produces:&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 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;5 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;6 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;7 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;8 = quack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;9 = quack&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the essence of &lt;strong&gt;duck typing&lt;/strong&gt;. The saying goes, &amp;ldquo;If it looks like a duck, swims like a duck, and quacks like a duck, then it probably &lt;em&gt;is&lt;/em&gt; a duck.&amp;rdquo; &lt;/p&gt;
&lt;p&gt;In other words, if the object has the needed methods, then it&amp;rsquo;s acceptable to pass it in, regardless of the object&amp;rsquo;s type. Duck or dynamic typing gives you an enormous amount of flexibility, as it allows any type to be used where it meets the required interfaces.&lt;/p&gt;
&lt;p&gt;However, there is a problem here. What happens if you pass in an object that &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; meet the required interface? For example, what if you pass in a number to &lt;code&gt;read_ten()&lt;/code&gt;, like this: &lt;code&gt;read_ten(3)&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;This results in an exception being thrown. Unless you catch the exception, your program will blow up with a &lt;a href=&quot;https://realpython.com/python-traceback/&quot;&gt;traceback&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;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;duck_test.py&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;read_ten&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_like_object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;AttributeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;int&amp;#39; object has no attribute &amp;#39;readline&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Dynamic typing can be quite a powerful tool, but as you can see, you must use caution when employing it.&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; Python and C++ are both considered &lt;a href=&quot;https://stackoverflow.com/a/11328980&quot;&gt;strongly typed&lt;/a&gt; languages. Although C++ has a stronger type system, the details of this are generally not significant to someone learning Python.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s move on to a feature that benefits from Python&amp;rsquo;s dynamic typing: templates.&lt;/p&gt;
&lt;h3 id=&quot;templates&quot;&gt;Templates&lt;/h3&gt;
&lt;p&gt;Python doesn&amp;rsquo;t have templates like C++, but it generally doesn&amp;rsquo;t need them. In Python, everything is a subclass of a single base type. This is what allows you to create duck typing functions like the ones above.&lt;/p&gt;
&lt;p&gt;The templating system in C++ allows you to create functions or algorithms that operate on multiple different types. This is quite powerful and can save you significant time and effort. However, it can also be a source of confusion and frustration, as compiler errors in templates can leave you baffled.&lt;/p&gt;
&lt;p&gt;Being able to use duck typing instead of templates makes some things much easier. But this, too, can cause hard-to-detect issues. As in all complex decisions, there are trade-offs when you&amp;rsquo;re comparing Python vs C++.&lt;/p&gt;
&lt;h3 id=&quot;type-checking&quot;&gt;Type Checking&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s been a lot of interest and discussion in the Python community lately about static type checking in Python. Projects like &lt;a href=&quot;http://mypy-lang.org/&quot;&gt;mypy&lt;/a&gt; have raised the possibility of adding pre-runtime type checking to specific spots in the language. This can be quite useful in managing interfaces between portions of large packages or specific APIs. &lt;/p&gt;
&lt;p&gt;It helps to address one of the downsides of duck typing. For developers using a function, it helps if they can fully understand what each parameter needs to be. This can be useful on large project teams where many developers need to communicate through APIs.&lt;/p&gt;
&lt;p&gt;Once again, let&amp;rsquo;s take a look at your Python vs C++ comparison chart:&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;Feature&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Faster Execution&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-Platform Execution&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single-Type Variables&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple-Type Variables&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comprehensions&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rich Set of Built-In Algorithms&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Static Typing&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Dynamic Typing&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Now you&amp;rsquo;re ready to move on to differences in object-oriented programming.&lt;/p&gt;
&lt;h2 id=&quot;object-oriented-programming&quot;&gt;Object-Oriented Programming&lt;/h2&gt;
&lt;p&gt;Like C++, Python supports an &lt;a href=&quot;https://realpython.com/courses/intro-object-oriented-programming-oop-python/&quot;&gt;object-oriented programming model&lt;/a&gt;. Many of the same concepts you learned in C++ carry over into Python. You&amp;rsquo;ll still need to make decisions about &lt;a href=&quot;https://realpython.com/inheritance-composition-python/&quot;&gt;inheritance, composition&lt;/a&gt;, and multiple inheritance.&lt;/p&gt;
&lt;h3 id=&quot;similarities&quot;&gt;Similarities&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://realpython.com/python-super/&quot;&gt;Inheritance&lt;/a&gt; between classes works similarly in Python vs C++. A new class can inherit methods and attributes from one or more base classes, just like you&amp;rsquo;ve seen in C++. Some of the details are a bit different, however. &lt;/p&gt;
&lt;p&gt;Base classes in Python do not have their constructor called automatically like they do in C++. This can be confusing when you&amp;rsquo;re switching languages.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://realpython.com/python-super/#super-in-multiple-inheritance&quot;&gt;Multiple inheritance&lt;/a&gt; also works in Python, and it has just as many quirks and strange rules as it does in C++.&lt;/p&gt;
&lt;p&gt;Similarly, you can also use composition to build classes, where you have objects of one type hold other types. Considering everything is an object in Python, this means that classes can hold anything else in the language.&lt;/p&gt;
&lt;h3 id=&quot;differences&quot;&gt;Differences&lt;/h3&gt;
&lt;p&gt;There are some differences, however, when you&amp;rsquo;re comparing Python vs C++. The first two are related.&lt;/p&gt;
&lt;p&gt;The first difference is that Python has no concept of access modifiers for classes. Everything in a class object is public. The Python community has developed a convention that any member of a class starting with a single underscore is treated as private. This is in no way enforced by the language, but it seems to work out pretty well.&lt;/p&gt;
&lt;p&gt;The fact that every class member and method is public in Python leads to the second difference: Python has far weaker encapsulation support than C++. &lt;/p&gt;
&lt;p&gt;As mentioned, the single underscore convention makes this far less of an issue in practical codebases than it is in a theoretical sense. In general, any user that breaks this rule and depends on the internal workings of a class is asking for trouble.&lt;/p&gt;
&lt;h3 id=&quot;operator-overloads-vs-dunder-methods&quot;&gt;Operator Overloads vs Dunder Methods&lt;/h3&gt;
&lt;p&gt;In C++, you can add &lt;strong&gt;operator overloads&lt;/strong&gt;. These allow you to define the behavior of specific syntactical operators (like &lt;code&gt;==&lt;/code&gt;) for certain data types. Usually, this is used to add more natural usage of your classes. For the &lt;code&gt;==&lt;/code&gt; operator, you can define exactly what it means for two objects of a class to be equal.&lt;/p&gt;
&lt;p&gt;One difference that takes some developers a long time to grasp is how to work around the lack of operator overloads in Python. It&amp;rsquo;s great that Python&amp;rsquo;s objects all work in any of the standard containers, but what if you want the &lt;code&gt;==&lt;/code&gt; operator to do a deep comparison between two objects of your new class? In C++, you would create an &lt;code&gt;operator==()&lt;/code&gt; in your class and do the comparison.&lt;/p&gt;
&lt;p&gt;Python has a similar structure that&amp;rsquo;s used quite consistently across the language: &lt;strong&gt;dunder methods&lt;/strong&gt;. Dunder methods get their name because they all start and end with a double underscore, or &amp;ldquo;d-under.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Many of the built-in functions that operate on objects in Python are handled by calls to that object&amp;rsquo;s &lt;a href=&quot;https://realpython.com/operator-function-overloading/&quot;&gt;dunder methods&lt;/a&gt;. For your example above, you can add &lt;code&gt;__eq__()&lt;/code&gt; to your class to do whatever fancy comparison you 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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyFancyComparisonClass&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;__eq__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This produces a class that compares the same way as any other instance of its class. Not particularly useful, but it demonstrates the point.&lt;/p&gt;
&lt;p&gt;There are a large number of dunder methods used in Python, and the built-in functions make use of them extensively. For example, adding &lt;code&gt;__lt__()&lt;/code&gt; will allow Python to compare the relative order of two of your objects. This means that not only will the &lt;code&gt;&amp;lt;&lt;/code&gt; operator now work, but that &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, and &lt;code&gt;&amp;gt;=&lt;/code&gt; will also work as well.&lt;/p&gt;
&lt;p&gt;Even better, if you have several objects of your new class in a list, then you can use &lt;code&gt;sorted()&lt;/code&gt; on the list and they&amp;rsquo;ll be sorted using &lt;code&gt;__lt__()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once again, let&amp;rsquo;s take a look at your Python vs C++ comparison chart:&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;Feature&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Faster Execution&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-Platform Execution&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single-Type Variables&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple-Type Variables&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comprehensions&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rich Set of Built-In Algorithms&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Static Typing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic Typing&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Strict Encapsulation&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Now that you&amp;rsquo;ve seen object-oriented coding across both languages, let&amp;rsquo;s look at how Python and C++ manage those objects in memory.&lt;/p&gt;
&lt;h2 id=&quot;memory-management&quot;&gt;Memory Management&lt;/h2&gt;
&lt;p&gt;One of the biggest differences, when you&amp;rsquo;re comparing Python vs C++, is how they handle memory. As you saw in the section about variables in C++ and Python&amp;rsquo;s names, Python does not have pointers, nor does it easily let you manipulate memory directly. While there are times when you want to have that level of control, most of the time it&amp;rsquo;s not necessary.&lt;/p&gt;
&lt;p&gt;Giving up direct control of memory locations brings a few benefits. You don&amp;rsquo;t need to worry about memory ownership, or making sure that memory is freed once (and only once) after it&amp;rsquo;s been allocated. You also never have to worry about whether or not an object was allocated on the stack or the heap, which tends to trip up beginning C++ developers.&lt;/p&gt;
&lt;p&gt;Python manages all of these issues for you. To do this everything in Python is a derived class from Python&amp;rsquo;s &lt;code&gt;object&lt;/code&gt;. This allows the Python interpreter to implement reference counting as a means of keeping track of which objects are still in use and which can be freed.&lt;/p&gt;
&lt;p&gt;This convenience comes at a price, of course. To free allocated memory objects for you, Python will occasionally need to run what is called a &lt;strong&gt;garbage collector&lt;/strong&gt;, which finds unused memory objects and frees them.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; CPython has a complex &lt;a href=&quot;https://realpython.com/python-memory-management/&quot;&gt;memory management scheme&lt;/a&gt;, which means that freeing memory doesn&amp;rsquo;t necessarily mean the memory gets returned to the operating system.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Python uses two tools to free memory: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The reference counting collector &lt;/li&gt;
&lt;li&gt;The generational collector&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s look at each of these individually.&lt;/p&gt;
&lt;h3 id=&quot;reference-counting-collector&quot;&gt;Reference Counting Collector&lt;/h3&gt;
&lt;p&gt;The reference counting collector is fundamental to the standard Python interpreter and is always running. It works by keeping track of how many times a given block of memory (which is always a Python &lt;code&gt;object&lt;/code&gt;) has a name attached to it while your program is running. Many rules describe when the reference count is incremented or decremented, but an example of one case might clarify:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;A long string&amp;#39;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above example, line 1 creates a new object containing the string &lt;code&gt;&quot;A long string&quot;&lt;/code&gt;. It then places the name &lt;code&gt;x&lt;/code&gt; on this object, increasing the object&amp;rsquo;s reference count to 1:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/cpp_ref_count_one.b70d0e13aa3b.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/cpp_ref_count_one.b70d0e13aa3b.png&quot; width=&quot;1083&quot; height=&quot;423&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_ref_count_one.b70d0e13aa3b.png&amp;amp;w=270&amp;amp;sig=ac9db469ce090231a1574e4f755b72c7b1cbfe1a 270w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_ref_count_one.b70d0e13aa3b.png&amp;amp;w=541&amp;amp;sig=99b17ede52a12cf46bab2b90949e903779eb4d82 541w, https://files.realpython.com/media/cpp_ref_count_one.b70d0e13aa3b.png 1083w&quot; sizes=&quot;75vw&quot; alt=&quot;A Python object with reference count of one.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On line 2 it assigns &lt;code&gt;y&lt;/code&gt; to name the same object, which will increase the reference count to 2:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/cpp_ref_count_two.199793fc702e.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/cpp_ref_count_two.199793fc702e.png&quot; width=&quot;1083&quot; height=&quot;663&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_ref_count_two.199793fc702e.png&amp;amp;w=270&amp;amp;sig=ec05c2b3594b82072f8a5eb00a8a48cf4ce8f85e 270w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_ref_count_two.199793fc702e.png&amp;amp;w=541&amp;amp;sig=7c70f6c76c862d08757a7a59a18366e336341250 541w, https://files.realpython.com/media/cpp_ref_count_two.199793fc702e.png 1083w&quot; sizes=&quot;75vw&quot; alt=&quot;A Python object with reference count of two.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you call &lt;code&gt;del&lt;/code&gt; with &lt;code&gt;x&lt;/code&gt; in line 3, you&amp;rsquo;re removing one of the references to the object, dropping the count back to 1:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/cpp_ref_count_one_one.47037ceb7f95.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/cpp_ref_count_one_one.47037ceb7f95.png&quot; width=&quot;1083&quot; height=&quot;936&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_ref_count_one_one.47037ceb7f95.png&amp;amp;w=270&amp;amp;sig=84975043d6c8f09a0954ceb440954bdd9722a79d 270w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_ref_count_one_one.47037ceb7f95.png&amp;amp;w=541&amp;amp;sig=79518a340b46d37283250339bfa36b853fc65060 541w, https://files.realpython.com/media/cpp_ref_count_one_one.47037ceb7f95.png 1083w&quot; sizes=&quot;75vw&quot; alt=&quot;Two Python objects, each with reference count of one.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally, when you remove &lt;code&gt;y&lt;/code&gt;, the final reference to the object, its reference count drops to zero and it can be freed by the reference counting garbage collector. It may or may not be freed immediately at this point, but generally, that shouldn&amp;rsquo;t matter to the developer:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/cpp_ref_count_zero_two.e3dff58e94b0.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/cpp_ref_count_zero_two.e3dff58e94b0.png&quot; width=&quot;1083&quot; height=&quot;933&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_ref_count_zero_two.e3dff58e94b0.png&amp;amp;w=270&amp;amp;sig=9a72e29c9fba7d1bb35de32206de9c8d812ddf2c 270w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cpp_ref_count_zero_two.e3dff58e94b0.png&amp;amp;w=541&amp;amp;sig=d2943e2c66f609c3a30d507ef877f22125b6d34e 541w, https://files.realpython.com/media/cpp_ref_count_zero_two.e3dff58e94b0.png 1083w&quot; sizes=&quot;75vw&quot; alt=&quot;The Python None object with reference count of two and another Python object with reference count of zero.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While this will take care of finding and freeing many of the objects that need to be freed, there are a few situations it will not catch. For that, you need the generational garbage collector.&lt;/p&gt;
&lt;h3 id=&quot;generational-garbage-collector&quot;&gt;Generational Garbage Collector&lt;/h3&gt;
&lt;p&gt;One of the big holes in the reference counting scheme is that your program can build a cycle of references, where object &lt;code&gt;A&lt;/code&gt; has a reference to object &lt;code&gt;B&lt;/code&gt;, which has a reference back to object &lt;code&gt;A&lt;/code&gt;. It&amp;rsquo;s entirely possible to hit this situation and have nothing in your code referring to either object. In this case, neither of the objects will ever hit a reference count of 0.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;generational garbage collector&lt;/strong&gt; involves a complex algorithm that is beyond the scope of this article, but it will find some of these orphaned reference cycles and free them for you. It runs on an occasional basis controlled by settings described &lt;a href=&quot;https://docs.python.org/3.7/library/gc.html&quot;&gt;in the documentation&lt;/a&gt;. One of these parameters is to disable this garbage collector entirely.&lt;/p&gt;
&lt;h3 id=&quot;when-you-dont-want-garbage-collection&quot;&gt;When You Don&amp;rsquo;t Want Garbage Collection&lt;/h3&gt;
&lt;p&gt;When you&amp;rsquo;re comparing Python vs C++, as when you&amp;rsquo;re comparing any two tools, each advantage comes with a trade-off. Python doesn&amp;rsquo;t require explicit memory management, but occasionally it will spend a longer amount of time than expected on garbage collection. The inverse is true for C++: your program will have consistent response times, but you&amp;rsquo;ll need to expend more effort in managing memory.&lt;/p&gt;
&lt;p&gt;In many programs the occasional garbage collection hit is unimportant. If you&amp;rsquo;re writing a script that only runs for 10 seconds, then you&amp;rsquo;re unlikely to notice the difference. Some situations, however, require consistent response times. Real-time systems are a great example, where responding to a piece of hardware in a fixed amount of time can be essential to the proper operation of your system.&lt;/p&gt;
&lt;p&gt;Systems with hard real-time requirements are some of the systems for which Python is a poor language choice. Having a tightly controlled system where you&amp;rsquo;re certain of the timing is a good use of C++. These are the types of issues to consider when you&amp;rsquo;re deciding on the language for a project.&lt;/p&gt;
&lt;p&gt;Time to update your Python vs C++ chart:&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;Feature&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Faster Execution&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-Platform Execution&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single-Type Variables&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple-Type Variables&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comprehensions&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rich Set of Built-In Algorithms&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Static Typing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic Typing&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strict Encapsulation&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Direct Memory Control&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Garbage Collection&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 id=&quot;threading-multiprocessing-and-async-io&quot;&gt;Threading, Multiprocessing, and Async IO&lt;/h2&gt;
&lt;p&gt;The concurrency models in C++ and Python are similar, but they have different results and benefits. Both languages have support for threading, multiprocessing, and Async IO operations. Let&amp;rsquo;s look at each of these.&lt;/p&gt;
&lt;h3 id=&quot;threading&quot;&gt;Threading&lt;/h3&gt;
&lt;p&gt;While both C++ and Python have threading built into the language, the results can be markedly different, depending on the problem you&amp;rsquo;re solving. Frequently, &lt;a href=&quot;https://realpython.com/intro-to-python-threading/&quot;&gt;threading&lt;/a&gt; is used to address performance problems. In C++, threading can provide a general speed-up for both computationally bound and I/O bound problems, as threads can take full advantage of the cores on a multiprocessor system.&lt;/p&gt;
&lt;p&gt;Python, on the other hand, has made a design trade-off to use the &lt;strong&gt;Global Interpreter Lock&lt;/strong&gt;, or the &lt;a href=&quot;https://realpython.com/python-gil/&quot;&gt;GIL&lt;/a&gt;, to simplify its threading implementation. There are many benefits to the GIL, but the drawback is that only one thread will be running at a single time, even if there are multiple cores.&lt;/p&gt;
&lt;p&gt;If your problem is I/O bound, like fetching several web pages at once, then this limitation will not bother you in the least. You&amp;rsquo;ll appreciate Python&amp;rsquo;s easier threading model and built-in methods for &lt;a href=&quot;https://docs.python.org/3/library/queue.html&quot;&gt;inter-thread communications&lt;/a&gt;. If your problem is CPU-bound, however, then the GIL will restrict your performance to that of a single processor. Fortunately, Python&amp;rsquo;s multiprocessing library has a similar interface to its threading library.&lt;/p&gt;
&lt;h3 id=&quot;multiprocessing&quot;&gt;Multiprocessing&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://realpython.com/python-concurrency/&quot;&gt;Multiprocessing&lt;/a&gt; support in Python is built into the standard library. It has a clean interface that allows you to spin up multiple processes and share information between them. You can create a pool of processes and spread work across them using several techniques. &lt;/p&gt;
&lt;p&gt;While Python still uses similar OS primitives to create the new processes, much of the low-level complication is hidden from the developer.&lt;/p&gt;
&lt;p&gt;C++ relies on &lt;code&gt;fork()&lt;/code&gt; to provide multiprocessing support. While this gives you direct access to all of the controls and issues of spawning multiple processes, it&amp;rsquo;s also much more complex.&lt;/p&gt;
&lt;h3 id=&quot;async-io&quot;&gt;Async IO&lt;/h3&gt;
&lt;p&gt;While both Python and C++ support Async IO routines, they&amp;rsquo;re handled differently. In C++, the &lt;code&gt;std::async&lt;/code&gt; methods are likely to use threading to achieve the Async IO nature of their operations. In Python, &lt;a href=&quot;https://realpython.com/async-io-python/&quot;&gt;Async IO&lt;/a&gt; code will only run on a single thread.&lt;/p&gt;
&lt;p&gt;There are trade-offs here as well. Using separate threads allows the C++ Async IO code to perform faster on computationally bound problems. The Python tasks used in its Async IO implementation are more lightweight, so it&amp;rsquo;s faster to spin up a large number of them to handle I/O bound issues.&lt;/p&gt;
&lt;p&gt;Your Python vs C++ comparison chart remains unchanged for this section. Both languages support a full range of concurrency options, with varying trade-offs between speed and convenience. &lt;/p&gt;
&lt;h2 id=&quot;miscellaneous-issues&quot;&gt;Miscellaneous Issues&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re comparing Python vs C++ and looking at adding Python to your toolbelt, then there are a few other things to consider. While your current editor or IDE will certainly work for Python, you might want to add certain extensions or language packs. It&amp;rsquo;s also worth giving &lt;a href=&quot;https://www.jetbrains.com/pycharm/&quot;&gt;PyCharm&lt;/a&gt; a look, as it&amp;rsquo;s Python-specific.&lt;/p&gt;
&lt;p&gt;Several C++ projects have Python bindings. Things like &lt;a href=&quot;https://www.qt.io/qt-for-python&quot;&gt;Qt&lt;/a&gt;, &lt;a href=&quot;https://docs.wxwidgets.org/3.0/overview_python.html&quot;&gt;WxWidgets&lt;/a&gt;, and many messaging APIs having multiple-language bindings.&lt;/p&gt;
&lt;p&gt;If you want to &lt;a href=&quot;https://www.codeproject.com/Articles/11805/Embedding-Python-in-C-C-Part-I&quot;&gt;embed Python in C++&lt;/a&gt;, then you can use the &lt;a href=&quot;https://docs.python.org/2/extending/embedding.html&quot;&gt;Python/C API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, there are several methods for using your C++ skills to extend Python and add functionality, or to call your existing C++ libraries from within your Python code. Tools like &lt;a href=&quot;https://dbader.org/blog/python-ctypes-tutorial&quot;&gt;CTypes&lt;/a&gt;, &lt;a href=&quot;https://cython.org/&quot;&gt;Cython&lt;/a&gt;, &lt;a href=&quot;https://dbader.org/blog/python-cffi&quot;&gt;CFFI&lt;/a&gt;, &lt;a href=&quot;https://www.boost.org/doc/libs/1_70_0/libs/python/doc/html/index.html&quot;&gt;Boost.Python&lt;/a&gt; and &lt;a href=&quot;http://www.swig.org/Doc3.0/Python.html&quot;&gt;Swig&lt;/a&gt; can help you combine these languages and use each for what it&amp;rsquo;s best at.&lt;/p&gt;
&lt;h2 id=&quot;summary-python-vs-c&quot;&gt;Summary: Python vs C++&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ve spent some time reading and thinking about the differences between Python vs C++. While Python has easier syntax and fewer sharp edges, it&amp;rsquo;s not a perfect fit for all problems. You&amp;rsquo;ve looked at the syntax, memory management, processing, and several other aspects of these two languages.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a final look at your Python vs C++ comparison chart:&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;Feature&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Faster Execution&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-Platform Execution&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single-Type Variables&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple-Type Variables&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comprehensions&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rich Set of Built-In Algorithms&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Static Typing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic Typing&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strict Encapsulation&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Direct Memory Control&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Garbage Collection&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;If you&amp;rsquo;re comparing Python vs C++, then you can see from your chart that this is not a case where one is better than the other. Each of them is a tool that&amp;rsquo;s well crafted for various use cases. Just like you don&amp;rsquo;t use a hammer for driving screws, using the right language for the job will make your life easier!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Congrats! You&amp;rsquo;ve now seen some of the strengths and weaknesses of both Python and C++. You&amp;rsquo;ve learned some of the features of each language and how they are similar.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve seen that C++ is great when you want:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fast execution speed (potentially at the cost of development speed)&lt;/li&gt;
&lt;li&gt;Complete control of memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Conversely, Python is great when you want:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fast development speed (potentially at the cost of execution speed)&lt;/li&gt;
&lt;li&gt;Managed memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You&amp;rsquo;re now ready to make a wise language choice when it comes to your next project!&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>Absolute vs Relative Imports in Python</title>
      <id>https://realpython.com/courses/absolute-vs-relative-imports-python/</id>
      <link href="https://realpython.com/courses/absolute-vs-relative-imports-python/"/>
      <updated>2019-09-10T14:00:00+00:00</updated>
      <summary>If you’ve worked on a Python project that has more than one file, chances are you’ve had to use an import statement before. In this course, you’ll not only cover the pros and cons of absolute and relative imports but also learn about the best practices for writing import statements.</summary>
      <content type="html">
        &lt;p&gt;If you&amp;rsquo;ve worked on a Python project that has more than one file, chances are you&amp;rsquo;ve had to use an &lt;code&gt;import&lt;/code&gt; statement before. Even for Pythonistas with a couple of projects under their belt, imports can be confusing! &lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re reading this because you&amp;rsquo;d like to gain a deeper understanding of imports in Python, particularly &lt;strong&gt;absolute&lt;/strong&gt; and &lt;strong&gt;relative imports&lt;/strong&gt;, then you&amp;rsquo;ve come to the right place! In this tutorial, you&amp;rsquo;ll learn the differences between the two, as well as their pros and cons.&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>MATLAB vs Python: Why and How to Make the Switch</title>
      <id>https://realpython.com/matlab-vs-python/</id>
      <link href="https://realpython.com/matlab-vs-python/"/>
      <updated>2019-09-09T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn about MATLAB vs Python, why you should switch from MATLAB to Python, the packages you&#39;ll need to make a smooth transition, and the bumps you&#39;ll most likely encounter along the way.</summary>
      <content type="html">
        &lt;p&gt;MATLAB® is widely known as a high-quality environment for any work that involves arrays, matrices, or linear algebra. Python is newer to this arena but is becoming increasingly popular for similar tasks. As you&amp;rsquo;ll see in this article, Python has all of the computational power of MATLAB for science tasks and makes it fast and easy to develop robust applications. However, there are some important differences when comparing MATLAB vs Python that you&amp;rsquo;ll need to learn about to effectively switch over.&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;Evaluate the differences of using MATLAB vs Python&lt;/li&gt;
&lt;li&gt;Set up an environment for Python that duplicates the majority of MATLAB functions&lt;/li&gt;
&lt;li&gt;Convert scripts from MATLAB to Python&lt;/li&gt;
&lt;li&gt;Avoid common issues you might have when switching from MATLAB to Python&lt;/li&gt;
&lt;li&gt;Write code that looks and feels like Python&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-numpy-learning-guide&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a free NumPy Resources Guide&lt;/a&gt; that points you to the best tutorials, videos, and books for improving your NumPy skills.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;matlab-vs-python-comparing-features-and-philosophy&quot;&gt;MATLAB vs Python: Comparing Features and Philosophy&lt;/h2&gt;
&lt;p&gt;Python is a high-level, general-purpose programming language designed for ease of use by human beings accomplishing all sorts of tasks. Python was created by Guido van Rossum and first released in the early 1990s. Python is a mature language developed by hundreds of collaborators around the world.&lt;/p&gt;
&lt;p&gt;Python is used by developers working on small, personal projects all the way up to some of the largest internet companies in the world. Not only does Python run &lt;a href=&quot;https://redditblog.com/2005/12/05/on-lisp/&quot;&gt;Reddit&lt;/a&gt; and &lt;a href=&quot;https://anvilventures.com/blog/looking-inside-the-box.html&quot;&gt;Dropbox&lt;/a&gt;, but the &lt;a href=&quot;https://stackoverflow.com/questions/2560310/heavy-usage-of-python-at-google/2561008#2561008&quot;&gt;original Google algorithm&lt;/a&gt; was written in Python. Also, the Python-based Django Framework runs &lt;a href=&quot;https://thenewstack.io/instagram-makes-smooth-move-python-3/&quot;&gt;Instagram&lt;/a&gt; and many other websites. On the science and engineering side, the data to create the &lt;a href=&quot;https://www.sciencenews.org/article/black-hole-first-picture-event-horizon-telescope&quot;&gt;2019 photo of a black hole&lt;/a&gt; was &lt;a href=&quot;https://github.com/achael/eht-imaging&quot;&gt;processed in Python&lt;/a&gt;, and major companies like &lt;a href=&quot;https://medium.com/netflix-techblog/python-at-netflix-86b6028b3b3e&quot;&gt;Netflix use Python&lt;/a&gt; in their data analytics work.&lt;/p&gt;
&lt;p&gt;There is also an important philosophical difference in the MATLAB vs Python comparison. &lt;strong&gt;MATLAB&lt;/strong&gt; is &lt;strong&gt;proprietary, closed-source&lt;/strong&gt; software. For most people, a license to use MATLAB is quite expensive, which means that if you have code in MATLAB, then only people who can afford a license will be able to run it. Plus, users are charged for each additional toolbox they want to install to extend the basic functionality of MATLAB. Aside from the cost, the MATLAB language is developed exclusively by Mathworks. If Mathworks were ever to go out of business, then MATLAB would no longer be able to be developed and might eventually stop functioning.&lt;/p&gt;
&lt;p&gt;On the other hand, &lt;strong&gt;Python&lt;/strong&gt; is &lt;strong&gt;free and open-source&lt;/strong&gt; software. Not only can you download Python at no cost, but you can also download, look at, and modify the source code as well. This is a big advantage for Python because it means that anyone can pick up the development of the language if the current developers were unable to continue for some reason.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re a researcher or scientist, then using open-source software has some pretty big benefits. &lt;a href=&quot;https://en.wikipedia.org/wiki/Paul_Romer&quot;&gt;Paul Romer&lt;/a&gt;, the 2018 Nobel Laureate in Economics, is a recent convert to Python. By his estimation, switching to open-source software in general, and Python in particular, brought greater integrity and accountability to his research. This was because all of the code could be shared and run by any interested reader. Prof. Romer wrote an excellent article, &lt;a href=&quot;https://paulromer.net/jupyter-mathematica-and-the-future-of-the-research-paper/&quot;&gt;Jupyter, Mathematica, and the Future of the Research Paper&lt;/a&gt;, about his experience with open-source software.&lt;/p&gt;
&lt;p&gt;Moreover, since Python is available at no cost, a much broader audience can use the code you develop. As you&amp;rsquo;ll see a little later on in the article, Python has an awesome community that can help you get started with the language and advance your knowledge. There are tens of thousands of tutorials, articles, and books all about Python software development. Here are a few to get you started:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-introduction/&quot;&gt;Introduction to Python 3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/learning-paths/python3-introduction/#&quot;&gt;Basic Data Types in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/learning-paths/python3-introduction/&quot;&gt;Python 3 Basics Learning Path&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Plus, with so many developers in the community, there are hundreds of thousands of free packages to accomplish many of the tasks that you&amp;rsquo;ll want to do with Python. You&amp;rsquo;ll learn more about how to get these packages later on in this article.&lt;/p&gt;
&lt;p&gt;Like &lt;strong&gt;MATLAB&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt; is an &lt;strong&gt;interpreted&lt;/strong&gt; language. This means that Python code can be ported between all of the major operating system platforms and CPU architectures out there, with only small changes required for different platforms. There are distributions of Python for desktop and laptop CPUs and microcontrollers like Adafruit. Python can also talk to other microcontrollers like Arduino with a simple programming interface that is almost identical no matter the host operating system.&lt;/p&gt;
&lt;p&gt;For all of these reasons, and many more, Python is an excellent choice to replace MATLAB as your programming language of choice. Now that you&amp;rsquo;re convinced to try out Python, read on to find out how to get it on your computer and how to switch from MATLAB!&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;a href=&quot;https://www.gnu.org/software/octave/&quot;&gt;GNU Octave&lt;/a&gt; is a free and open-source clone of MATLAB. In this sense, GNU Octave has the same philosophical advantages that Python has around code reproducibility and access to the software.&lt;/p&gt;
&lt;p&gt;Octave&amp;rsquo;s syntax is mostly compatible with MATLAB syntax, so it provides a short learning curve for MATLAB developers who want to use open-source software. However, Octave can&amp;rsquo;t match Python&amp;rsquo;s community or the number of different kinds of applications that Python can serve, so we definitely recommend you switch whole hog over to Python.&lt;/p&gt;
&lt;p&gt;Besides, this website is called &lt;em&gt;Real Python&lt;/em&gt;, not &lt;em&gt;Real Octave&lt;/em&gt; 😀&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;setting-up-your-environment-for-python&quot;&gt;Setting Up Your Environment for Python&lt;/h2&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll learn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to install Python on your computer for a seamless transition from MATLAB&lt;/li&gt;
&lt;li&gt;How to install replacements for the MATLAB integrated development environment&lt;/li&gt;
&lt;li&gt;How to use the replacements for MATLAB on your computer&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;getting-python-via-anaconda&quot;&gt;Getting Python via Anaconda&lt;/h3&gt;
&lt;p&gt;Python can be downloaded from a number of different sources, called &lt;strong&gt;distributions&lt;/strong&gt;. For instance, the Python that you can download from the &lt;a href=&quot;https://python.org&quot;&gt;official Python website&lt;/a&gt; is one distribution. Another very popular Python distribution, particularly for math, science, engineering, and data science applications, is the &lt;a href=&quot;https://anaconda.com&quot;&gt;Anaconda distribution&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are two main reasons that Anaconda is so popular:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Anaconda distributes pre-built packages for Windows, macOS, and Linux, which means that the installation process is really easy and the same for all three major platforms.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Anaconda includes all of the most popular packages for engineering and data science type workloads in one single installer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the purposes of creating an environment that is very similar to MATLAB, you should download and &lt;a href=&quot;https://anaconda.com/download&quot;&gt;install Anaconda&lt;/a&gt;. As of this writing, there are two major versions of Python available: Python 2 and Python 3. You should definitely install the version of Anaconda for Python 3, since Python 2 will not be supported past January 1, 2020. Python 3.7 is the most recent version at the time of this writing, but Python 3.8 should be out a few months after this article is published. Either 3.7 or 3.8 will work the same for you, so choose the most recent version you can.&lt;/p&gt;
&lt;p&gt;Once you have downloaded the Anaconda installer, you can follow the default set up procedures depending on your platform. You should install Anaconda in a directory that does not require administrator permission to modify, which is the default setting in the installer.&lt;/p&gt;
&lt;p&gt;With Anaconda installed, there are a few specific programs you should know about. The easiest way to launch applications is to use the Anaconda Navigator. On Windows, you can find this in the Start Menu and on macOS you can find it in Launchpad. Here&amp;rsquo;s a screenshot of the Anaconda Navigator on Windows:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/anaconda-navigator.bff710edb0a0.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/anaconda-navigator.bff710edb0a0.png&quot; width=&quot;1023&quot; height=&quot;761&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/anaconda-navigator.bff710edb0a0.png&amp;amp;w=255&amp;amp;sig=4e334e506ec75eef5dffa2b1873e7e70a8124776 255w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/anaconda-navigator.bff710edb0a0.png&amp;amp;w=511&amp;amp;sig=c179d42d0bfe9b4ab5db42446ae216cbdf21c615 511w, https://files.realpython.com/media/anaconda-navigator.bff710edb0a0.png 1023w&quot; sizes=&quot;75vw&quot; alt=&quot;Main Anaconda Navigator window showing installed applications&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the screenshot, you can see several installed applications, including &lt;strong&gt;JupyterLab&lt;/strong&gt;, &lt;strong&gt;Jupyter Notebook&lt;/strong&gt;, and &lt;strong&gt;Spyder&lt;/strong&gt;, that you&amp;rsquo;ll learn more about later in this tutorial.&lt;/p&gt;
&lt;p&gt;On Windows, there is one other application that you should know about. This is called &lt;strong&gt;Anaconda Prompt&lt;/strong&gt;, and it is a command prompt set up specifically to work with &lt;code&gt;conda&lt;/code&gt; on Windows. If you want to type &lt;code&gt;conda&lt;/code&gt; commands in a terminal, rather than using the Navigator GUI, then you should use Anaconda Prompt on Windows.&lt;/p&gt;
&lt;p&gt;On macOS, you can use any terminal application such as the default Terminal.app or iTerm2 to access &lt;code&gt;conda&lt;/code&gt; from the command line. On Linux, you can use the terminal emulator of your choice and which specific emulator is installed will depend on your Linux distribution.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Terminology Note:&lt;/strong&gt; You may be a little bit confused about &lt;code&gt;conda&lt;/code&gt; versus Anaconda. The distinction is subtle but important. &lt;strong&gt;Anaconda&lt;/strong&gt; is a distribution of Python that includes many of the necessary packages for scientific work of all kinds. &lt;strong&gt;&lt;code&gt;conda&lt;/code&gt;&lt;/strong&gt; is a cross-platform package management software that is included with the Anaconda distribution of Python. &lt;code&gt;conda&lt;/code&gt; is the software that you use to build, install, and remove packages within the Anaconda distribution.&lt;/p&gt;
&lt;p&gt;You can read all about how to use &lt;code&gt;conda&lt;/code&gt; in &lt;a href=&quot;https://realpython.com/python-windows-machine-learning-setup/&quot;&gt;Setting Up Python for Machine Learning on Windows&lt;/a&gt;. Although that tutorial focuses on Windows, the &lt;code&gt;conda&lt;/code&gt; commands are the same on Windows, macOS, and Linux.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Python also includes another way to install packages, called &lt;code&gt;pip&lt;/code&gt;. If you&amp;rsquo;re using Anaconda, you should always prefer to install packages using &lt;code&gt;conda&lt;/code&gt; whenever possible. Sometimes, though, a package is only available with &lt;code&gt;pip&lt;/code&gt;, and for those cases, you can read &lt;a href=&quot;https://realpython.com/what-is-pip/&quot;&gt;What Is Pip? A Guide for New Pythonistas&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;getting-an-integrated-development-environment&quot;&gt;Getting an Integrated Development Environment&lt;/h3&gt;
&lt;p&gt;One of the big advantages of MATLAB is that it includes a development environment with the software. This is the window that you&amp;rsquo;re most likely used to working in. There is a console in the center where you can type commands, a variable explorer on the right, and a directory listing on the left.&lt;/p&gt;
&lt;p&gt;Unlike MATLAB, Python itself does not have a default development environment. It is up to each user to find one that fits their needs. Fortunately, Anaconda comes with two different integrated development environments (IDEs) that are similar to the MATLAB IDE to make your switch seamless. These are called Spyder and JupyterLab. In the next two sections, you&amp;rsquo;ll see a detailed introduction to Spyder and a brief overview of JupyterLab.&lt;/p&gt;
&lt;h3 id=&quot;spyder&quot;&gt;Spyder&lt;/h3&gt;
&lt;p&gt;Spyder is an IDE for Python that is developed specifically for scientific Python work. One of the really nice things about Spyder is that it has a mode specifically designed for people like you who are converting from MATLAB to Python. You&amp;rsquo;ll see that a little later on.&lt;/p&gt;
&lt;p&gt;First, you should open Spyder. If you followed the instructions in the previous section, you can open Spyder using the Anaconda Navigator. Just find the Spyder icon and click the &lt;em&gt;Launch&lt;/em&gt; button. You can also launch Spyder from the Start Menu if you&amp;rsquo;re using Windows or from Launchpad if you&amp;rsquo;re using macOS.&lt;/p&gt;
&lt;h4 id=&quot;changing-the-default-window-layout-in-spyder&quot;&gt;Changing the Default Window Layout in Spyder&lt;/h4&gt;
&lt;p&gt;The default window in Spyder looks like the image below. This is for version 3.3.4 of Spyder running on Windows 10. It should look quite similar on macOS or Linux:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/spyder-default.0ad112e1eb06.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/spyder-default.0ad112e1eb06.png&quot; width=&quot;995&quot; height=&quot;772&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spyder-default.0ad112e1eb06.png&amp;amp;w=248&amp;amp;sig=0839a0f3d02e0ac8130933cdab634d9734f01c69 248w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spyder-default.0ad112e1eb06.png&amp;amp;w=497&amp;amp;sig=6def5d7ca1ff225d6c692aed90dd09fb3b089633 497w, https://files.realpython.com/media/spyder-default.0ad112e1eb06.png 995w&quot; sizes=&quot;75vw&quot; alt=&quot;Spyder IDE&amp;#39;s default view&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Before you take a tour of the user interface, you can make the interface look a little more like MATLAB. In the &lt;em&gt;View → Window layouts&lt;/em&gt; menu choose &lt;em&gt;MATLAB layout.&lt;/em&gt; That will change the window automatically so it has the same areas that you&amp;rsquo;re used to from MATLAB, annotated on the figure below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/spyder-matlab-view.c9e6fbfcffe4.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/spyder-matlab-view.c9e6fbfcffe4.png&quot; width=&quot;989&quot; height=&quot;784&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spyder-matlab-view.c9e6fbfcffe4.png&amp;amp;w=247&amp;amp;sig=548bc886f46177bc4d9635ebc75e81850fc6a14c 247w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spyder-matlab-view.c9e6fbfcffe4.png&amp;amp;w=494&amp;amp;sig=82510255efbd739bfc6d1357e9f7428e9259b000 494w, https://files.realpython.com/media/spyder-matlab-view.c9e6fbfcffe4.png 989w&quot; sizes=&quot;75vw&quot; alt=&quot;Spyder IDE&amp;#39;s MATLAB like view&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the top left of the window is the &lt;em&gt;File Explorer&lt;/em&gt; or &lt;strong&gt;directory listing&lt;/strong&gt;. In this pane, you can find files that you want to edit or create new files and folders to work with.&lt;/p&gt;
&lt;p&gt;In the top center is a file editor. In this editor, you can work on Python scripts that you want to save to re-run later on. By default, the editor opens a file called &lt;code&gt;temp.py&lt;/code&gt; located in Spyder&amp;rsquo;s configuration directory. This file is meant as a temporary place to try things out before you save them in a file somewhere else on your computer.&lt;/p&gt;
&lt;p&gt;In the bottom center is the console. Like in MATLAB, the console is where you can run commands to see what they do or when you want to debug some code. Variables created in the console are not saved if you close Spyder and open it up again. The console is technically running &lt;a href=&quot;https://ipython.org/&quot;&gt;IPython&lt;/a&gt; by default.&lt;/p&gt;
&lt;p&gt;Any commands that you type in the console will be logged into the history file in the bottom right pane of the window. Furthermore, any variables that you create in the console will be shown in the variable explorer in the top right pane.&lt;/p&gt;
&lt;p&gt;Notice that you can adjust the size of any pane by putting your mouse over the divider between panes, clicking, and dragging the edge to the size that you want. You can close any of the panes by clicking the &lt;em&gt;x&lt;/em&gt; in the top of the pane.&lt;/p&gt;
&lt;p&gt;You can also break any pane out of the main window by clicking the button that looks like two windows in the top of the pane, right next to the &lt;em&gt;x&lt;/em&gt; that closes the pane. When a pane is broken out of the main window, you can drag it around and rearrange it however you want. If you want to put the pane back in the main window, drag it with the mouse so a transparent blue or gray background appears and the neighboring panes resize, then let go and the pane will snap into place.&lt;/p&gt;
&lt;p&gt;Once you have the panes arranged exactly how you want, you can ask Spyder to save the layout. Go to the &lt;em&gt;View&lt;/em&gt; menu and find the &lt;em&gt;Window layouts&lt;/em&gt; flyout again. Then click &lt;em&gt;Save current layout&lt;/em&gt; and give it a name. This lets you reset to your preferred layout at any time if something gets changed by accident. You can also reset to one of the default configurations from this menu.&lt;/p&gt;
&lt;h4 id=&quot;running-statements-in-the-console-in-spyder&quot;&gt;Running Statements in the Console in Spyder&lt;/h4&gt;
&lt;p&gt;In this section, you&amp;rsquo;re going to be writing some simple Python commands, but don&amp;rsquo;t worry if you don&amp;rsquo;t quite understand what they mean yet. You&amp;rsquo;ll learn more about Python syntax a little later on in this article. What you want to do right now is get a sense for how Spyder&amp;rsquo;s interface is similar to and different from the MATLAB interface.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll be working a lot with the Spyder console in this article, so you should learn about how it works. In the console, you&amp;rsquo;ll see a line that starts with &lt;code&gt;In [1]:&lt;/code&gt;, for input line 1. Spyder (really, the IPython console) numbers all of the input lines that you type. Since this is the first input you&amp;rsquo;re typing, the line number is 1. In the rest of this article, you&amp;rsquo;ll see references to &amp;ldquo;input line X,&amp;rdquo; where X is the number in the square brackets.&lt;/p&gt;
&lt;p&gt;One of the first things I like to do with folks who are new to Python is show them the &lt;a href=&quot;https://www.python.org/dev/peps/pep-0020/&quot;&gt;&lt;em&gt;Zen of Python&lt;/em&gt;&lt;/a&gt;. This short poem gives you a sense of what Python is all about and how to approach working with Python.&lt;/p&gt;
&lt;p&gt;To see the &lt;em&gt;Zen of Python&lt;/em&gt;, type &lt;code&gt;import this&lt;/code&gt; on input line 1 and then run the code by pressing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;. You&amp;rsquo;ll see an output like 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;In [1]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;this&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The Zen of Python, by Tim Peters&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Beautiful is better than ugly.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Explicit is better than implicit.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Simple is better than complex.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Complex is better than complicated.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Flat is better than nested.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Sparse is better than dense.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Readability counts.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Special cases aren&amp;#39;t special enough to break the rules.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Although practicality beats purity.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Errors should never pass silently.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Unless explicitly silenced.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;In the face of ambiguity, refuse the temptation to guess.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;There should be one-- and preferably only one --obvious way to do it.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Although that way may not be obvious at first unless you&amp;#39;re Dutch.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Now is better than never.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Although never is often better than *right* now.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;If the implementation is hard to explain, it&amp;#39;s a bad idea.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;If the implementation is easy to explain, it may be a good idea.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Namespaces are one honking great idea -- let&amp;#39;s do more of those!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code has &lt;code&gt;import this&lt;/code&gt; on input line 1. The output from running &lt;code&gt;import this&lt;/code&gt; is to print the &lt;em&gt;Zen of Python&lt;/em&gt; onto the console. We&amp;rsquo;ll return to several of the stanzas in this poem later on in the article.&lt;/p&gt;
&lt;p&gt;In many of the code blocks in this article, you&amp;rsquo;ll see three greater-than signs (&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;) in the top right of the code block. If you click that, it will remove the input prompt and any output lines, so you can copy and paste the code right into your console.&lt;/p&gt;
&lt;p&gt;Many Pythonistas maintain a healthy sense of humor. This is displayed in many places throughout the language, including the &lt;em&gt;Zen of Python&lt;/em&gt;. For another one, in the Spyder console, type the following code, followed by &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; to run it:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;antigravity&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That statement will open your web browser to the webcomic called &lt;em&gt;XKCD&lt;/em&gt;, specifically comic &lt;a href=&quot;https://xkcd.com/353&quot;&gt;#353&lt;/a&gt;, where the author has discovered that Python has given him the ability to fly!&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve now successfully run your first two Python statements! Congratulations 😃🎉&lt;/p&gt;
&lt;p&gt;If you look at the History Log, you should see the first two commands you typed in the console (&lt;code&gt;import this&lt;/code&gt; and &lt;code&gt;import antigravity&lt;/code&gt;). Let&amp;rsquo;s define some variables and do some basic arithmetic now. In the console, type the following statements, pressing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; after each one:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_1&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;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var_2&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_3&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[6]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you defined 3 variables: &lt;code&gt;var_1&lt;/code&gt;, &lt;code&gt;var_2&lt;/code&gt;, and &lt;code&gt;var_3&lt;/code&gt;. You assigned &lt;code&gt;var_1&lt;/code&gt; the value 10, &lt;code&gt;var_2&lt;/code&gt; the value 20, and &lt;code&gt;var_3&lt;/code&gt; the sum of &lt;code&gt;var_1&lt;/code&gt; and &lt;code&gt;var_2&lt;/code&gt;. Then you showed the value of the &lt;code&gt;var_3&lt;/code&gt; variable by writing it as the only thing on the input line. The output from that statement is shown on the next &lt;code&gt;Out&lt;/code&gt; line, and the number on the &lt;code&gt;Out&lt;/code&gt; line matches the associated &lt;code&gt;In&lt;/code&gt; line.&lt;/p&gt;
&lt;p&gt;There are two main things for you to notice in these commands:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If a statement does not include an assignment (with an &lt;code&gt;=&lt;/code&gt;), it is printed onto an &lt;code&gt;Out&lt;/code&gt; line. In MATLAB, you would need to include a semicolon to suppress the output even from assignment statements, but that is not necessary in Python.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On input lines 3, 4, and 5, the &lt;em&gt;Variable explorer&lt;/em&gt; in the top right pane updated.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After you run these three commands, your &lt;em&gt;Variable explorer&lt;/em&gt; should look like the image below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/spyder-variable-explorer.bed4ebb8ed14.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/spyder-variable-explorer.bed4ebb8ed14.png&quot; width=&quot;236&quot; height=&quot;224&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spyder-variable-explorer.bed4ebb8ed14.png&amp;amp;w=59&amp;amp;sig=e2a27248dbe723f1c1983bc9305c822208b95c4f 59w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spyder-variable-explorer.bed4ebb8ed14.png&amp;amp;w=118&amp;amp;sig=555db3d1dca6b4244a7bfc427217207c5abb10d9 118w, https://files.realpython.com/media/spyder-variable-explorer.bed4ebb8ed14.png 236w&quot; sizes=&quot;75vw&quot; alt=&quot;Spyder IDE&amp;#39;s Variable Explorer&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this image, you can see a table with four columns:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Name&lt;/em&gt;&lt;/strong&gt; shows the name that you gave to &lt;code&gt;var_1&lt;/code&gt;, &lt;code&gt;var_2&lt;/code&gt;, and &lt;code&gt;var_3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Type&lt;/em&gt;&lt;/strong&gt; shows the Python type of the variable, in this case, all &lt;code&gt;int&lt;/code&gt; for integer numbers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Size&lt;/em&gt;&lt;/strong&gt; shows the size of the data stored variable, which is more useful for lists and other data structures.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Value&lt;/em&gt;&lt;/strong&gt; shows the current value of the variable.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;running-code-in-files-in-spyder&quot;&gt;Running Code in Files in Spyder&lt;/h4&gt;
&lt;p&gt;The last stop in our brief tour of the Spyder interface is the File editor pane. In this pane, you can create and edit Python scripts and run them using the console. By default, Spyder creates a temporary file called &lt;code&gt;temp.py&lt;/code&gt; which is intended for you to temporarily store commands as you&amp;rsquo;re working before you move or save them in another file.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s write some code into the &lt;code&gt;temp.py&lt;/code&gt; file and see how to run it. The file starts with the following code, which you can just leave in place:&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;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;Spyder Editor&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;sd&quot;&gt;This is a temporary script file.&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you can see two Python syntax structures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Line 1 has a comment. In Python, the comment character is the hash or pound sign (&lt;code&gt;#&lt;/code&gt;). MATLAB uses the percent symbol (&lt;code&gt;%&lt;/code&gt;) as the comment character. Anything following the hash on the line is a comment and is usually ignored by the Python interpreter.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Starting on line 2 is a string that provides some context for the contents of the file. This is often referred to as a &lt;strong&gt;documentation string&lt;/strong&gt; or &lt;strong&gt;docstring&lt;/strong&gt; for short. You&amp;rsquo;ll learn more about docstrings in &lt;a href=&quot;#comments-start-with-in-python&quot;&gt;a later section&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you can start adding code to this file. Starting on line 8 in &lt;code&gt;temp.py&lt;/code&gt;, enter the following code that is similar to what you already typed in the console:&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; 8 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_4&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;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var_4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var_5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, there are three ways to run the code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You can use the &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-f5&quot;&gt;F5&lt;/kbd&gt;&lt;/span&gt; keyboard shortcut to run the file just like in MATLAB.&lt;/li&gt;
&lt;li&gt;You can click the green right-facing triangle in the menu bar just above the &lt;em&gt;Editor&lt;/em&gt; and &lt;em&gt;File explorer&lt;/em&gt; panes.&lt;/li&gt;
&lt;li&gt;You can use the &lt;em&gt;Run → Run&lt;/em&gt; menu option.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first time you run a file, Spyder will open a dialog window asking you to confirm the options you want to use. For this test, the default options are fine and you can click &lt;em&gt;Run&lt;/em&gt; at the bottom of the dialog box:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/spyder-run-settings.784e177e3ab9.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/spyder-run-settings.784e177e3ab9.png&quot; width=&quot;440&quot; height=&quot;525&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spyder-run-settings.784e177e3ab9.png&amp;amp;w=110&amp;amp;sig=8ea221b7e2d3d3f5430e174ffeca679f91c03167 110w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spyder-run-settings.784e177e3ab9.png&amp;amp;w=220&amp;amp;sig=826f3f0b51456fdb72cd6d4270ffda1cc9e9b3b7 220w, https://files.realpython.com/media/spyder-run-settings.784e177e3ab9.png 440w&quot; sizes=&quot;75vw&quot; alt=&quot;Spyder IDE&amp;#39;s Run Settings dialog box&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This will automatically execute the following code in the console:&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;In [7]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;C:/Users/Eleanor/.spyder-py3/temp.py&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;   ...: &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;wdir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;C:/Users/Eleanor/.spyder-py3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code will run the file that you were working on. Notice that running the file added three variables into the Variable explorer: &lt;code&gt;var_4&lt;/code&gt;, &lt;code&gt;var_5&lt;/code&gt;, and &lt;code&gt;var_6&lt;/code&gt;. These are the three variables that you defined in the file. You will also see &lt;code&gt;runfile()&lt;/code&gt; added to the History log.&lt;/p&gt;
&lt;p&gt;In Spyder, you can also create code cells that can be run individually. To create a code cell, add a line that starts with &lt;code&gt;# %%&lt;/code&gt; into the file open in the editor:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# %% This is a code cell&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_7&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var_7&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# %% This is a second code cell&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;This code will be executed in this cell&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have created your first code cell on line 11 with the &lt;code&gt;# %%&lt;/code&gt; code. What follows is a line comment and is ignored by Python. On line 12, you are assigning &lt;code&gt;var_7&lt;/code&gt; to have the value 42 and then line 13 assigns &lt;code&gt;var_8&lt;/code&gt; to be &lt;code&gt;var_7&lt;/code&gt; times two. Line 15 starts another code cell that can be executed separately from the first one.&lt;/p&gt;
&lt;p&gt;To execute the code cells, click the &lt;em&gt;Run Current Cell&lt;/em&gt; or &lt;em&gt;Run Current Cell and Go to the Next One&lt;/em&gt; buttons next to the generic &lt;em&gt;Run&lt;/em&gt; button in the toolbar. You can also use the keyboard shortcuts &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-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; to run the current cell and leave it selected, or &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; to run the current cell and select the next cell.&lt;/p&gt;
&lt;p&gt;Spyder also offers easy-to-use debugging features, just like in MATLAB. You can double-click any of the line numbers in the &lt;em&gt;Editor&lt;/em&gt; to set a breakpoint in your code. You can run the code in debug mode using the blue right-facing triangle with two vertical lines from the toolbar, or the &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-f5&quot;&gt;F5&lt;/kbd&gt;&lt;/span&gt; keyboard shortcut. This will pause execution at any breakpoints you specify and open the &lt;code&gt;ipdb&lt;/code&gt; debugger in the console which is an IPython-enhanced way to run the Python debugger &lt;code&gt;pdb&lt;/code&gt;. You can read more in &lt;a href=&quot;https://realpython.com/python-debugging-pdb/&quot;&gt;Python Debugging With pdb&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;summarizing-your-experience-in-spyder&quot;&gt;Summarizing Your Experience in Spyder&lt;/h4&gt;
&lt;p&gt;Now you have the basic tools to use Spyder as a replacement for the MATLAB integrated development environment. You know how to run code in the console or type code into a file and run the file. You also know where to look to see your directories and files, the variables that you&amp;rsquo;ve defined, and the history of the commands you typed.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;re ready to start organizing your code into modules and packages, you can check out the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-modules-packages/&quot;&gt;Python Modules and Packages – An Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/pypi-publish-python-package/&quot;&gt;How to Publish an Open-Source Python Package to PyPI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/courses/how-to-publish-your-own-python-package-pypi/&quot;&gt;How to Publish Your Own Python Package to PyPI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Spyder is a really big piece of software, and you&amp;rsquo;ve only just scratched the surface. You can learn a lot more about Spyder by reading the &lt;a href=&quot;https://docs.spyder-ide.org/index.html&quot;&gt;official documentation&lt;/a&gt;, the &lt;a href=&quot;https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ&quot;&gt;troubleshooting and FAQ guide&lt;/a&gt;, and the &lt;a href=&quot;https://github.com/spyder-ide/spyder/wiki&quot;&gt;Spyder wiki&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;jupyterlab&quot;&gt;JupyterLab&lt;/h3&gt;
&lt;p&gt;JupyterLab is an IDE developed by Project Jupyter. You may have heard of Jupyter Notebooks, particularly if you&amp;rsquo;re a data scientist. Well, JupyterLab is the next iteration of the Jupyter Notebook. Although at the time of this writing JupyterLab is still in beta, Project Jupyter expects that JupyterLab will eventually replace the current Notebook server interface. However, JupyterLab is fully compatible with existing Notebooks so the transition should be fairly seamless.&lt;/p&gt;
&lt;p&gt;JupyterLab comes preinstalled with Anaconda, so you can launch it from the Anaconda Navigator. Find the JupyterLab box and click &lt;em&gt;Launch&lt;/em&gt;. This will open your web browser to the address &lt;code&gt;http://localhost:8888/lab&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The main JupyterLab window is shown in the picture below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/jupyterlab-main-window.d9420a33f736.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/jupyterlab-main-window.d9420a33f736.png&quot; width=&quot;671&quot; height=&quot;740&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/jupyterlab-main-window.d9420a33f736.png&amp;amp;w=167&amp;amp;sig=121cf34a99d209ab6bd29ab6c9e194decc6b3ead 167w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/jupyterlab-main-window.d9420a33f736.png&amp;amp;w=335&amp;amp;sig=be3acce1805c6923d2f75141e51bc14ac526e154 335w, https://files.realpython.com/media/jupyterlab-main-window.d9420a33f736.png 671w&quot; sizes=&quot;75vw&quot; alt=&quot;JupyterLab&amp;#39;s Main Window&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are two main sections of the interface:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On the left is a &lt;em&gt;File explorer&lt;/em&gt; that lets you open files from your computer.&lt;/li&gt;
&lt;li&gt;On the right side of the window is how you can open create new Notebook files, work in an IPython console or system terminal, or create a new text file.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you&amp;rsquo;re interested in learning more about JupyterLab, you can read a lot more about the next evolution of the Notebook in the &lt;a href=&quot;https://blog.jupyter.org/jupyterlab-is-ready-for-users-5a6f039b8906&quot;&gt;blog post announcing the beta release&lt;/a&gt; or in the &lt;a href=&quot;https://jupyterlab.readthedocs.io/en/stable/&quot;&gt;JupyterLab documentation&lt;/a&gt;. You can also learn about the Notebook interface in &lt;a href=&quot;https://realpython.com/jupyter-notebook-introduction/&quot;&gt;Jupyter Notebook: An Introduction&lt;/a&gt; and the &lt;a href=&quot;https://realpython.com/courses/using-jupyter-notebooks/&quot;&gt;Using Jupyter Notebooks&lt;/a&gt; course. One neat thing about the Jupyter Notebook-style document is that the code cells you created in Spyder are very similar to the code cells in a Jupyter Notebook.&lt;/p&gt;
&lt;h2 id=&quot;learning-about-pythons-mathematical-libraries&quot;&gt;Learning About Python&amp;rsquo;s Mathematical Libraries&lt;/h2&gt;
&lt;p&gt;Now you&amp;rsquo;ve got Python on your computer and you&amp;rsquo;ve got an IDE where you feel at home. So how do you learn about how to actually accomplish a task in Python? With MATLAB, you can use a search engine to find the topic you&amp;rsquo;re looking for just by including &lt;code&gt;MATLAB&lt;/code&gt; in your query. With Python, you&amp;rsquo;ll usually get better search results if you can be a bit more specific in your query than just including &lt;code&gt;Python&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll take the next step to really feeling comfortable with Python by learning about how Python functionality is divided into several libraries. You&amp;rsquo;ll also learn what each library does so you can get top-notch results with your searches!&lt;/p&gt;
&lt;p&gt;Python is sometimes called a &lt;strong&gt;batteries-included&lt;/strong&gt; language. This means that most of the important functions you need are already included when you install Python. For instance, Python has a &lt;code&gt;math&lt;/code&gt; library and a &lt;code&gt;statistics&lt;/code&gt; library built-in that include the basic operations.&lt;/p&gt;
&lt;p&gt;Sometimes, though, you want to do something that isn&amp;rsquo;t included in the language. One of the big advantages of Python is that someone else has probably done whatever you need to do and published the code to accomplish that task. There are &lt;em&gt;several hundred-thousand&lt;/em&gt; publicly available and free packages that you can easily install to perform various tasks. These range from processing PDF files to building and hosting an interactive website to working with highly optimized mathematical and scientific functions.&lt;/p&gt;
&lt;p&gt;Working with arrays or matrices, optimization, or plotting requires additional libraries to be installed. Fortunately, if you install Python with the Anaconda installer these libraries come preinstalled and you don&amp;rsquo;t need to worry. Even if you&amp;rsquo;re not using Anaconda, they are usually pretty easy to install for most operating systems.&lt;/p&gt;
&lt;p&gt;The set of important libraries you&amp;rsquo;ll need to switch over from MATLAB are typically called the &lt;strong&gt;SciPy stack&lt;/strong&gt;. At the base of the stack are libraries that provide fundamental array and matrix operations (&lt;strong&gt;NumPy&lt;/strong&gt;), integration, optimization, signal processing, and linear algebra functions (&lt;strong&gt;SciPy&lt;/strong&gt;), and plotting (&lt;strong&gt;Matplotlib&lt;/strong&gt;). Other libraries that build on these to provide more advanced functionality include &lt;strong&gt;Pandas&lt;/strong&gt;, &lt;strong&gt;scikit-learn&lt;/strong&gt;, &lt;strong&gt;SymPy&lt;/strong&gt;, and more.&lt;/p&gt;
&lt;h3 id=&quot;numpy-numerical-python&quot;&gt;NumPy (Numerical Python)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.numpy.org&quot;&gt;NumPy&lt;/a&gt; is probably the most fundamental package for scientific computing in Python. It provides a highly efficient interface to create and interact with multi-dimensional arrays. Nearly every other package in the SciPy stack uses or integrates with NumPy in some way.&lt;/p&gt;
&lt;p&gt;NumPy arrays are the equivalent to the basic array data structure in MATLAB. With NumPy arrays, you can do things like inner and outer products, transposition, and element-wise operations. NumPy also contains a number of useful methods for reading text and binary data files, fitting polynomial functions, many mathematical functions (sine, cosine, square root, and so on), and generating random numbers.&lt;/p&gt;
&lt;p&gt;The performance-sensitive parts of NumPy are all written in the C language, so they are very fast. NumPy can also take advantage of optimized linear algebra libraries such as Intel&amp;rsquo;s MKL or OpenBLAS to further increase performance.&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;/p&gt;
&lt;p&gt;&lt;em&gt;Real Python&lt;/em&gt; has &lt;a href=&quot;https://realpython.com/tutorials/numpy/&quot;&gt;several articles&lt;/a&gt; that cover how you can use NumPy to speed up your Python code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/numpy-array-programming/&quot;&gt;Look Ma, No For-Loops: Array Programming With NumPy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/how-to-use-numpy-arange/&quot;&gt;NumPy arange(): How to Use np.arange()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-histograms/&quot;&gt;Python Histogram Plotting: NumPy, Matplotlib, Pandas &amp;amp; Seaborn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&quot;scipy-scientific-python&quot;&gt;SciPy (Scientific Python)&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.scipy.org/doc/scipy/reference/&quot;&gt;SciPy&lt;/a&gt; package (as distinct from the SciPy stack) is a library that provides a huge number of useful functions for scientific applications. If you need to do work that requires optimization, linear algebra or sparse linear algebra, discrete Fourier transforms, signal processing, physical constants, image processing, or numerical integration, then SciPy is the library for you! Since SciPy implements so many different features, it&amp;rsquo;s almost like having access to a bunch of the MATLAB toolboxes in one package.&lt;/p&gt;
&lt;p&gt;SciPy relies heavily on NumPy arrays to do its work. Like NumPy, many of the algorithms in SciPy are implemented in C or Fortran, so they are also very fast. Also like NumPy, SciPy can take advantage of optimized linear algebra libraries to further improve performance.&lt;/p&gt;
&lt;h3 id=&quot;matplotlib-matlab-like-plotting-library&quot;&gt;Matplotlib (MATLAB-like Plotting Library)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://matplotlib.org&quot;&gt;Matplotlib&lt;/a&gt; is a library to produce high-quality and interactive two-dimensional plots. Matplotlib is designed to provide a plotting interface that is similar to the &lt;code&gt;plot()&lt;/code&gt; function in MATLAB, so people switching from MATLAB should find it somewhat familiar. Although the core functions in Matplotlib are for 2-D data plots, there are extensions available that allow plotting in three dimensions with the &lt;a href=&quot;https://matplotlib.org/3.1.0/api/toolkits/mplot3d.html&quot;&gt;mplot3d&lt;/a&gt; package, plotting geographic data with &lt;a href=&quot;https://scitools.org.uk/cartopy/docs/latest/&quot;&gt;cartopy&lt;/a&gt;, and many more listed in the &lt;a href=&quot;https://matplotlib.org/3.1.0/thirdpartypackages/index.html&quot;&gt;Matplotlib documentation&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;Here are some more resources on Matplotlib:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-matplotlib-guide/&quot;&gt;Python Plotting With Matplotlib (Guide)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://matplotlib.org/tutorials/introductory/sample_plots.html&quot;&gt;Matplotlib Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://matplotlib.org/gallery/index.html&quot;&gt;Matplotlib Gallery&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&quot;other-important-python-libraries&quot;&gt;Other Important Python Libraries&lt;/h3&gt;
&lt;p&gt;With NumPy, SciPy, and Matplotlib, you can switch a lot of your MATLAB code to Python. But there are a few more libraries that might be helpful to know about.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;&lt;strong&gt;Pandas&lt;/strong&gt;&lt;/a&gt; provides a DataFrame, an array with the ability to name rows and columns for easy access.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sympy.org/en/index.html&quot;&gt;&lt;strong&gt;SymPy&lt;/strong&gt;&lt;/a&gt; provides symbolic mathematics and a computer algebra system.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://scikit-learn.org/stable/index.html&quot;&gt;&lt;strong&gt;scikit-learn&lt;/strong&gt;&lt;/a&gt; provides many functions related to machine learning tasks.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://scikit-image.org/&quot;&gt;&lt;strong&gt;scikit-image&lt;/strong&gt;&lt;/a&gt; provides functions related to image processing, compatible with the similar library in SciPy.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/&quot;&gt;&lt;strong&gt;Tensorflow&lt;/strong&gt;&lt;/a&gt; provides a common platform for many machine learning tasks.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://keras.io/&quot;&gt;&lt;strong&gt;Keras&lt;/strong&gt;&lt;/a&gt; provides a library to generate neural networks.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/multiprocessing.html&quot;&gt;&lt;strong&gt;multiprocessing&lt;/strong&gt;&lt;/a&gt; provides a way to perform multi-process based parallelism. It&amp;rsquo;s built into Python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pint.readthedocs.io&quot;&gt;&lt;strong&gt;Pint&lt;/strong&gt;&lt;/a&gt; provides a unit library to conduct automatic conversion between physical unit systems.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pytables.org/&quot;&gt;&lt;strong&gt;PyTables&lt;/strong&gt;&lt;/a&gt; provides a reader and writer for HDF5 format files.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.pymc.io/&quot;&gt;&lt;strong&gt;PyMC3&lt;/strong&gt;&lt;/a&gt; provides Bayesian statistical modeling and probabilistic machine learning functionality.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;syntax-differences-between-matlab-and-python&quot;&gt;Syntax Differences Between MATLAB® and Python&lt;/h2&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll learn how to convert your MATLAB code into Python code. You&amp;rsquo;ll learn about the main syntax differences between MATLAB and Python, see an overview of basic array operations and how they differ between MATLAB and Python, and find out about some ways to attempt automatic conversion of your code.&lt;/p&gt;
&lt;p&gt;The biggest technical difference between MATLAB and Python is that in MATLAB, everything is treated as an array, while in Python everything is a more general object. For instance, in MATLAB, strings are arrays of characters or arrays of strings, while in Python, strings have their own type of object called &lt;code&gt;str&lt;/code&gt;. This has profound consequences for how you approach coding in each language, as you&amp;rsquo;ll see below.&lt;/p&gt;
&lt;p&gt;With that out of the way, let&amp;rsquo;s get started! To help you, the sections below are organized into groups based on how likely you are to run into that syntax.&lt;/p&gt;
&lt;h3 id=&quot;you-will-probably-see-this-syntax&quot;&gt;You Will Probably See This Syntax&lt;/h3&gt;
&lt;p&gt;The examples in this section represent code that you are very likely to see in the wild. These examples also demonstrate some of the more basic Python language features. You should make sure that you have a good grasp of these examples before moving on.&lt;/p&gt;
&lt;h4 id=&quot;comments-start-with-in-python&quot;&gt;Comments Start With &lt;code&gt;#&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, a comment is anything that follows a percent sign (&lt;code&gt;%&lt;/code&gt;) on a line. In Python, comments are anything that follow the hash or pound sign (&lt;code&gt;#&lt;/code&gt;). You already saw a Python comment in the earlier section about Spyder. In general, the Python interpreter ignores the content of comments, just like the MATLAB interpreter, so you can write whatever content you want in the comment. One exception to this rule in Python is the example you saw earlier in the section about Spyder:&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;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the Python interpreter reads this line, it will set the encoding that it uses to read the rest of the file. This comment must appear in one of the first two lines of the file to be valid.&lt;/p&gt;
&lt;p&gt;Another difference between MATLAB and Python is in how inline documentation is written. In MATLAB, documentation is written at the start of a function &lt;a href=&quot;https://www.mathworks.com/help/matlab/matlab_prog/add-help-for-your-program.html&quot;&gt;in a comment&lt;/a&gt;, like the code sample below:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;[total] &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;num_1,num_2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% ADDITION  Adds two numbers together&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%   TOTAL = ADDITION(NUM_1,NUM_2) adds NUM_1 and NUM_2 together&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%   See also SUM and PLUS&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, Python does not use comments in this way. Instead, Python has an idea called &lt;strong&gt;documentation strings&lt;/strong&gt; or &lt;a href=&quot;https://www.python.org/dev/peps/pep-0257/&quot;&gt;&lt;strong&gt;docstrings&lt;/strong&gt;&lt;/a&gt; for short. In Python, you would document the MATLAB function shown above like this:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addition&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;n&quot;&gt;num_2&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;Adds two numbers together.&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;    Example&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    -------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;gt;&amp;gt;&amp;gt; total = addition(10, 20)&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;gt;&amp;gt;&amp;gt; total&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    30&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice in this code that the docstring is between two sets of three quote characters (&lt;code&gt;&quot;&quot;&quot;&lt;/code&gt;). This allows the docstring to run onto multiple lines with the whitespace and newlines preserved. The triple quote characters are a special case of &lt;a href=&quot;https://docs.python.org/3/tutorial/introduction.html#strings&quot;&gt;&lt;strong&gt;string literals&lt;/strong&gt;&lt;/a&gt;. Don&amp;rsquo;t worry too much about the syntax of defining a function yet. You&amp;rsquo;ll see more about that &lt;a href=&quot;#function-definitions-start-with-def-and-return-values-in-python&quot;&gt;in a later section&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;whitespace-at-the-beginning-of-a-line-is-significant-in-python&quot;&gt;Whitespace at the Beginning of a Line Is Significant in Python&lt;/h4&gt;
&lt;p&gt;When you write code in MATLAB, blocks like &lt;code&gt;if&lt;/code&gt; statements, &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;while&lt;/code&gt; loops, and function definitions are finished with the &lt;code&gt;end&lt;/code&gt; keyword. It is generally considered a good practice in MATLAB to indent the code within the blocks so that the code is visually grouped together, but it is not syntactically necessary.&lt;/p&gt;
&lt;p&gt;For example, the following two blocks of code are functionally equivalent in MATLAB:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&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;num&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;lineno&quot;&gt; 2 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&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;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&amp;quot;&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;else&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&amp;quot;&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;end&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;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;am&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outside&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are first creating &lt;code&gt;num&lt;/code&gt; to store the value 10 and then checking whether the value of &lt;code&gt;num&lt;/code&gt; is equal to 10. If it is, you are displaying the phrase &lt;code&gt;num is equal to 10&lt;/code&gt; on the console from line 2. Otherwise, the &lt;code&gt;else&lt;/code&gt; clause will kick in and display &lt;code&gt;num is not equal to 10&lt;/code&gt;. Of course, if you run this code, you will see the &lt;code&gt;num is equal to 10&lt;/code&gt; output and then &lt;code&gt;I am now outside the if block&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now you should modify your code so it looks like the sample below:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&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;num&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;lineno&quot;&gt; 2 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&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;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&amp;quot;&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;else&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&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;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;am&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outside&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have only changed lines 3 and 5 by adding some spaces or indentation in the front of the line. The code will perform identically to the previous example code, but with the indentation, it is much easier to tell what code goes in the &lt;code&gt;if&lt;/code&gt; part of the statement and what code is in the &lt;code&gt;else&lt;/code&gt; part of the statement.&lt;/p&gt;
&lt;p&gt;In Python, indentation at the start of a line is used to delimit the beginning and end of class and function definitions, &lt;code&gt;if&lt;/code&gt; statements, and &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;while&lt;/code&gt; loops. There is no &lt;code&gt;end&lt;/code&gt; keyword in Python. This means that indentation is very important in Python!&lt;/p&gt;
&lt;p&gt;In addition, in Python the definition line of an &lt;code&gt;if/else/elif&lt;/code&gt; statement, a &lt;code&gt;for&lt;/code&gt; or &lt;code&gt;while&lt;/code&gt; loop, a function, or a class is ended by a colon. In MATLAB, the colon is not used to end the line.&lt;/p&gt;
&lt;p&gt;Consider this code example:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&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;lineno&quot;&gt; 2 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&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;lineno&quot;&gt; 4 &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;num is equal to 10&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;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num is not equal to 10&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;lineno&quot;&gt; 8 &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;I am now outside the if block&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the first line, you are defining &lt;code&gt;num&lt;/code&gt; and setting its value to 10. On line 2, writing &lt;code&gt;if num == 10:&lt;/code&gt; tests the value of &lt;code&gt;num&lt;/code&gt; compared to 10. Notice the colon at the end of the line.&lt;/p&gt;
&lt;p&gt;Next, line 3 &lt;em&gt;must&lt;/em&gt; be indented in Python&amp;rsquo;s syntax. On that line, you are using &lt;code&gt;print()&lt;/code&gt; to display some output to the console, in a similar way to &lt;code&gt;disp()&lt;/code&gt; in MATLAB. You&amp;rsquo;ll read more about &lt;code&gt;print()&lt;/code&gt; versus &lt;code&gt;disp()&lt;/code&gt; &lt;a href=&quot;#console-output-is-shown-with-print-in-python&quot;&gt;in a later section&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On line 4, you are starting the &lt;code&gt;else&lt;/code&gt; block. Notice that the &lt;code&gt;e&lt;/code&gt; in the &lt;code&gt;else&lt;/code&gt; keyword is vertically aligned with the &lt;code&gt;i&lt;/code&gt; in the &lt;code&gt;if&lt;/code&gt; keyword, and the line is ended by a colon. Because the &lt;code&gt;else&lt;/code&gt; is dedented relative to &lt;code&gt;print()&lt;/code&gt; on line 3, and because it is aligned with the &lt;code&gt;if&lt;/code&gt; keyword, Python knows that the code within the &lt;code&gt;if&lt;/code&gt; part of the block has finished and the &lt;code&gt;else&lt;/code&gt; part is starting. Line 5 is indented by one level, so it forms the block of code to be executed when the &lt;code&gt;else&lt;/code&gt; statement is satisfied.&lt;/p&gt;
&lt;p&gt;Lastly, on line 6 you are printing a statement from outside the &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; block. This statement will be printed regardless of the value of &lt;code&gt;num&lt;/code&gt;. Notice that the &lt;code&gt;p&lt;/code&gt; in &lt;code&gt;print()&lt;/code&gt; is vertically aligned with the &lt;code&gt;i&lt;/code&gt; in &lt;code&gt;if&lt;/code&gt; and the &lt;code&gt;e&lt;/code&gt; in &lt;code&gt;else&lt;/code&gt;. This is how Python knows that the code in the &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; block has ended. If you run the code above, Python will display &lt;code&gt;num is equal to 10&lt;/code&gt; followed by &lt;code&gt;I am now outside the if block&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now you should modify the code above to remove the indentation and see what happens. If you try to type the code without indentation into the Spyder/IPython console, you will get an &lt;code&gt;IndentationError&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;In [1]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&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;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&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;gp&quot;&gt;   ...: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num is equal to 10&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;  File&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt; &amp;quot;&amp;lt;ipython-input-2-f453ffd2bc4f&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;gt&quot;&gt;, line &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;num is equal to 10&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;ne&quot;&gt;IndentationError&lt;/span&gt;: expected an indented block
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you first set the value of &lt;code&gt;num&lt;/code&gt; to 10 and then tried to write the &lt;code&gt;if&lt;/code&gt; statement without indentation. In fact, the IPython console is smart and automatically indents the line after the &lt;code&gt;if&lt;/code&gt; statement for you, so you&amp;rsquo;ll have to delete the indentation to produce this error.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re indenting your code, the official Python style guide called &lt;a href=&quot;#there-is-an-official-guide-to-writing-good-code-in-python&quot;&gt;PEP 8&lt;/a&gt; recommends using 4 space characters to represent one indentation level. Most text editors that are set up to work with Python files will automatically insert 4 spaces if you press the &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-tab&quot;&gt;Tab&lt;/kbd&gt;&lt;/span&gt; key on your keyboard. You can choose to use the tab character for your code if you want, but you shouldn&amp;rsquo;t mix tabs and spaces or you&amp;rsquo;ll probably end up with a &lt;code&gt;TabError&lt;/code&gt; if the indentation becomes mismatched.&lt;/p&gt;
&lt;h4 id=&quot;conditional-statements-use-elif-in-python&quot;&gt;Conditional Statements Use &lt;code&gt;elif&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, you can construct &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/if.html&quot;&gt;conditional statements&lt;/a&gt; with &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;elseif&lt;/code&gt;, and &lt;code&gt;else&lt;/code&gt;. These kinds of statements allow you to control the flow of your program in response to different conditions.&lt;/p&gt;
&lt;p&gt;You should try this idea out with the code below, and then compare the example of MATLAB vs Python for conditional statements:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&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;num&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;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&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;lineno&quot;&gt; 3 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&amp;quot;&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;hll&quot;&gt;&lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&amp;quot;&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;else&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;neither&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nor&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&amp;quot;&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;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code block, you are defining &lt;code&gt;num&lt;/code&gt; to be equal to 10. Then you are checking if the value of &lt;code&gt;num&lt;/code&gt; is 10, and if it is, using &lt;code&gt;disp()&lt;/code&gt; to print output to the console. If &lt;code&gt;num&lt;/code&gt; is 20, you are printing a different statement, and if &lt;code&gt;num&lt;/code&gt; is neither 10 nor 20, you are printing the third statement.&lt;/p&gt;
&lt;p&gt;In Python, the &lt;code&gt;elseif&lt;/code&gt; keyword is replaced with &lt;code&gt;elif&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; 1 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&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;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&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;lineno&quot;&gt; 3 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num is equal to 10&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;hll&quot;&gt;&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 5 &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;num is equal to 20&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;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num is neither 10 nor 20&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 block is functionally equivalent to the previous MATLAB code block. There are 2 main differences. On line 4, &lt;code&gt;elseif&lt;/code&gt; is replaced with &lt;code&gt;elif&lt;/code&gt;, and there is no &lt;code&gt;end&lt;/code&gt; statement to end the block. Instead, the &lt;code&gt;if&lt;/code&gt; block ends when the next dedented line of code is found after the &lt;code&gt;else&lt;/code&gt;. You can read more in the &lt;a href=&quot;https://docs.python.org/3/tutorial/controlflow.html#if-statements&quot;&gt;Python documentation&lt;/a&gt; for &lt;code&gt;if&lt;/code&gt; statements.&lt;/p&gt;
&lt;h4 id=&quot;calling-functions-and-indexing-sequences-use-different-brackets-in-python&quot;&gt;Calling Functions and Indexing Sequences Use Different Brackets in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, when you want to call a function or when you want to index an array, you use round brackets (&lt;code&gt;()&lt;/code&gt;), sometimes also called parentheses. Square brackets (&lt;code&gt;[]&lt;/code&gt;) are used to create arrays.&lt;/p&gt;
&lt;p&gt;You can test out the differences in MATLAB vs Python with the example code below:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;mi&quot;&gt;20&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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    10&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    60&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you first create an array using the square brackets on the right side of the equal sign. Then, you retrieve the value of the first element by &lt;code&gt;arr(1)&lt;/code&gt;, using the round brackets as the indexing operator. On the third input line, you are calling &lt;code&gt;sum()&lt;/code&gt; and using the round brackets to indicate the parameters that should be passed into &lt;code&gt;sum()&lt;/code&gt;, in this case just &lt;code&gt;arr&lt;/code&gt;. MATLAB computes the sum of the elements in &lt;code&gt;arr&lt;/code&gt; and returns that result.&lt;/p&gt;
&lt;p&gt;Python uses separate syntax for calling functions and indexing sequences. In Python, using round brackets means that a function should be executed and using square brackets will index a sequence:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [1]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&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;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [3]: &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;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;60&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are defining a Python list on input line 1. Python lists have some important distinctions from arrays in MATLAB and arrays from the NumPy package. You can read more about Python lists in &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;Lists and Tuples in Python&lt;/a&gt;, and you&amp;rsquo;ll learn more about NumPy arrays in &lt;a href=&quot;#an-overview-of-basic-array-operations&quot;&gt;a later section&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the input line 2, you are displaying the value of the first element of the list with the indexing operation using square brackets. On input line 3, you are calling &lt;code&gt;sum()&lt;/code&gt; using round brackets and passing in the list stored in &lt;code&gt;arr&lt;/code&gt;. This results in the sum of the list elements being displayed on the last line. Notice that Python uses square brackets for indexing the list and round brackets for calling functions.&lt;/p&gt;
&lt;h4 id=&quot;the-first-index-in-a-sequence-is-0-in-python&quot;&gt;The First Index in a Sequence Is 0 in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, you can get the first value from an array by using &lt;code&gt;1&lt;/code&gt; as the index. This style follows the natural numbering convention and starts how you would count the number of items in the sequence. You can try out the differences of MATLAB vs Python with this example:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;mi&quot;&gt;20&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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    10&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;Array indices must be positive integers or logical values.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating an array with three numbers: &lt;code&gt;10&lt;/code&gt;, &lt;code&gt;20&lt;/code&gt;, and &lt;code&gt;30&lt;/code&gt;. Then you are displaying the value of the first element with the index &lt;code&gt;1&lt;/code&gt;, which is &lt;code&gt;10&lt;/code&gt;. Trying to access the zeroth element results in an error in MATLAB, as shown on the last two lines.&lt;/p&gt;
&lt;p&gt;In Python, the index of the first element in a sequence is 0, not 1:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [1]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&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;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;20&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;a string&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_string&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;gh&quot;&gt;Out[5]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_string&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;gh&quot;&gt;Out[6]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;&amp;#39; &amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are defining &lt;code&gt;arr&lt;/code&gt; as a Python list with three elements on input line 1. On input line 2, you are displaying the value of the first element of the list, which has the index 0. Then you are displaying the second element of the list, which has the index 1.&lt;/p&gt;
&lt;p&gt;On input lines 4, 5, and 6, you are defining &lt;code&gt;a_string&lt;/code&gt; with the contents &lt;code&gt;&quot;a string&quot;&lt;/code&gt; and then getting the first and second elements of the string. Notice that the second element (character) of the string is a space. This demonstrates a general Python feature, that many variable types operate as sequences and can be indexed, including lists, tuples, strings, and arrays.&lt;/p&gt;
&lt;h4 id=&quot;the-last-element-of-a-sequence-has-index-1-in-python&quot;&gt;The Last Element of a Sequence Has Index &lt;code&gt;-1&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, you can get the last value from an array by using &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/end.html&quot;&gt;&lt;code&gt;end&lt;/code&gt;&lt;/a&gt; as the index. This is really useful when you don&amp;rsquo;t know how long an array is, so you don&amp;rsquo;t know what number to access the last value.&lt;/p&gt;
&lt;p&gt;Try out the differences in MATLAB vs Python with this example:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;mi&quot;&gt;20&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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating an array with three numbers, &lt;code&gt;10&lt;/code&gt;, &lt;code&gt;20&lt;/code&gt;, and &lt;code&gt;30&lt;/code&gt;. Then you are displaying the value of the last element with the index &lt;code&gt;end&lt;/code&gt;, which is &lt;code&gt;30&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Python, the last value in a sequence can be retrieved by using the index &lt;code&gt;-1&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;In [1]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&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;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are defining a Python list with three elements on input line 1. On input line 2, you are displaying the value of the last element of the list, which has the index &lt;code&gt;-1&lt;/code&gt; and the value 30.&lt;/p&gt;
&lt;p&gt;In fact, by using negative numbers as the index values you can work your way backwards through the sequence:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;20&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&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;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[4]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are retrieving the second-to-last and third-to-last elements from the list, which have values of &lt;code&gt;20&lt;/code&gt; and &lt;code&gt;10&lt;/code&gt;, respectively.&lt;/p&gt;
&lt;h4 id=&quot;exponentiation-is-done-with-in-python&quot;&gt;Exponentiation Is Done With &lt;code&gt;**&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, when you want to raise a number to a power you use the &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/mpower.html&quot;&gt;caret operator&lt;/a&gt; (&lt;code&gt;^&lt;/code&gt;). The caret operator is a &lt;strong&gt;binary operator&lt;/strong&gt; that takes two numbers.  Other binary operators include addition (&lt;code&gt;+&lt;/code&gt;), subtraction (&lt;code&gt;-&lt;/code&gt;), multiplication (&lt;code&gt;*&lt;/code&gt;), and division (&lt;code&gt;/&lt;/code&gt;), among others. The number on the left of the caret is the base and the number on the right is the exponent.&lt;/p&gt;
&lt;p&gt;Try out the differences of MATLAB vs Python with this example:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;^&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    100&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are raising 10 to the power of 2 using the caret resulting an answer of 100.&lt;/p&gt;
&lt;p&gt;In Python, you use two asterisks (&lt;code&gt;**&lt;/code&gt;) when you want to raise a number to a power:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[1]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;100&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are raising 10 to the power of 2 using two asterisks resulting an answer of 100. Notice that there is no effect of including spaces on either side of the asterisks. In Python, the typical style is to have spaces on both sides of a binary operator.&lt;/p&gt;
&lt;h4 id=&quot;the-length-of-a-sequence-is-found-with-len-in-python&quot;&gt;The Length of a Sequence Is Found With &lt;code&gt;len()&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, you can get the length of an array with &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/length.html&quot;&gt;&lt;code&gt;length()&lt;/code&gt;&lt;/a&gt;. This function takes an array as the argument and returns back the size of the largest dimension in the array. You can see the basics of this function with this example:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&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;go&quot;&gt;ans =&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; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, on the first input line you are finding the length of an array with 3 elements. As expected, &lt;code&gt;length()&lt;/code&gt; returns an answer of 3. On the second input line, you are finding the length of the &lt;strong&gt;string array&lt;/strong&gt; that contains one element. Notice that MATLAB implicitly creates a string array, even though you did not use the square brackets to indicate it is an array.&lt;/p&gt;
&lt;p&gt;In Python, you can get the length of a sequence with &lt;code&gt;len()&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;In [1]: &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;mi&quot;&gt;10&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;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[1]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;3&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [2]: &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;s2&quot;&gt;&amp;quot;a string&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, on the input line 1 you are finding the length of a list with 3 elements. As expected, &lt;code&gt;len()&lt;/code&gt; returns a length of 3. On input line 2, you are finding the length of a string as the input. In Python, strings are sequences and &lt;code&gt;len()&lt;/code&gt; counts the number of characters in the string. In this case, &lt;code&gt;a string&lt;/code&gt; has 8 characters.&lt;/p&gt;
&lt;h4 id=&quot;console-output-is-shown-with-print-in-python&quot;&gt;Console Output Is Shown With &lt;code&gt;print()&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, you can use &lt;code&gt;disp()&lt;/code&gt;, &lt;code&gt;fprintf()&lt;/code&gt;, and &lt;code&gt;sprintf()&lt;/code&gt; to print the value of variables and other output to the console. &lt;code&gt;disp()&lt;/code&gt; is the simplest of these commands but does not give you any control over the format of the output. &lt;code&gt;fprintf()&lt;/code&gt; and &lt;code&gt;sprintf()&lt;/code&gt; give you total control over the output format, but the format specification is a little bit complicated.&lt;/p&gt;
&lt;p&gt;In Python, &lt;code&gt;print()&lt;/code&gt; serves the same function as &lt;code&gt;disp()&lt;/code&gt;. Unlike &lt;code&gt;disp()&lt;/code&gt;, &lt;code&gt;print()&lt;/code&gt; can send its output to a file similar to &lt;code&gt;fprintf()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Python&amp;rsquo;s &lt;code&gt;print()&lt;/code&gt; will display any number of arguments passed to it, separating them by a space in the output. This is different from &lt;code&gt;disp()&lt;/code&gt; in MATLAB, which only takes one argument. The following example shows how Python&amp;rsquo;s &lt;code&gt;print()&lt;/code&gt; can take any number of arguments, and the each argument is separated by a space in the output:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val_1&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;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;any number of arguments&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [4]: &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;val_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;10 20 any number of arguments&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, the input lines 1, 2, and 3 define &lt;code&gt;val_1&lt;/code&gt;, &lt;code&gt;val_2&lt;/code&gt;, and &lt;code&gt;str_1&lt;/code&gt;, where &lt;code&gt;val_1&lt;/code&gt; and &lt;code&gt;val_1&lt;/code&gt; are integers, and &lt;code&gt;str_1&lt;/code&gt; is a string of text. On input line 4, you are printing the three variables using &lt;code&gt;print()&lt;/code&gt;. The output below this line the value of the three variables are shown in the console output, separated by spaces.&lt;/p&gt;
&lt;p&gt;You can control the separator used in the output between arguments to &lt;code&gt;print()&lt;/code&gt; by using the &lt;code&gt;sep&lt;/code&gt; keyword argument:&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;In [5]: &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;val_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&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;10; 20; any number of arguments&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are printing the same three variables but setting the separator to be a semicolon followed by a space. This separator is printed between the first and second and the second and third arguments, but not after the third argument. To control the character printed after the last value, you can use the &lt;code&gt;end&lt;/code&gt; keyword argument to &lt;code&gt;print()&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;In [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;val_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&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;end&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;10; 20; any number of arguments;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have added the &lt;code&gt;end&lt;/code&gt; keyword argument to &lt;code&gt;print()&lt;/code&gt;, setting it to print a semicolon after the last value. This is shown in the output on line below the input.&lt;/p&gt;
&lt;p&gt;Like &lt;code&gt;disp()&lt;/code&gt; from MATLAB, &lt;code&gt;print()&lt;/code&gt; cannot directly control the output format of variables. If you want more control over the format of the output, you should use &lt;strong&gt;f-strings&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;format()&lt;/code&gt;&lt;/strong&gt;. In these strings, you can use very similar formatting style codes as &lt;code&gt;fprintf()&lt;/code&gt; in MATLAB to format numbers. You can read a lot more about f-strings and other string formatting in &lt;a href=&quot;https://realpython.com/python-f-strings/&quot;&gt;Python 3&amp;rsquo;s f-Strings&lt;/a&gt; or the &lt;a href=&quot;https://docs.python.org/3/library/string.html#format-specification-mini-language&quot;&gt;official documentation&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;In [7]: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Python&amp;#39;s print() can handle &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{str_1}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Python&amp;#39;s print() can handle any number of arguments&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [8]: &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;The value of val_1 = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{val_1:8.3f}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The value of val_1 =   10.000&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [9]: &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# The following line will only work in Python 3.8&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [10]: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;The value of {val_1=} and {val_2=}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The value of val_1 = 10, and val_2 = 20&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, input line 7 includes an f-string, indicated by the &lt;code&gt;f&lt;/code&gt; to start the string. This means that Python will substitute the value of any variables it encounters between &lt;code&gt;{}&lt;/code&gt;, or curly braces, within the string. You can see that in the output, Python has replaced &lt;code&gt;{str_1}&lt;/code&gt; with &lt;code&gt;any number of arguments&lt;/code&gt;, the value of &lt;code&gt;str_1&lt;/code&gt;. On input line 8, you are using some of the formatting syntax to print the value of &lt;code&gt;val_1&lt;/code&gt; as a floating point number with 8 columns in the output and 3 digits of precision.&lt;/p&gt;
&lt;p&gt;On input line 10, a new feature that is coming in Python 3.8 (due out in &lt;a href=&quot;https://www.python.org/dev/peps/pep-0569/&quot;&gt;late 2019&lt;/a&gt;) is demonstrated. If a variable name is immediately followed by an equals sign inside curly braces, the name of the variable and the value will be printed automatically.&lt;/p&gt;
&lt;p&gt;You can take a deep dive into Python&amp;rsquo;s &lt;code&gt;print()&lt;/code&gt; by checking out &lt;a href=&quot;https://realpython.com/python-print/&quot;&gt;The Ultimate Guide to Python Print&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;you-will-probably-see-these-but-you-can-learn-them-when-you-need-to&quot;&gt;You Will Probably See These, but You Can Learn Them When You Need To&lt;/h3&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll find examples of code that you&amp;rsquo;ll probably see in the wild, but you can wait a little while to understand them if you want. These examples use some intermediate features in Python but are still in the core of how Python works. Just like in the last section, you&amp;rsquo;ll see comparisons of the MATLAB vs Python syntax differences.&lt;/p&gt;
&lt;h4 id=&quot;function-definitions-start-with-def-and-return-values-in-python&quot;&gt;Function Definitions Start With &lt;code&gt;def&lt;/code&gt; and &lt;code&gt;return&lt;/code&gt; Values in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, you can &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/function.html&quot;&gt;define a function&lt;/a&gt; by placing the &lt;code&gt;function&lt;/code&gt; keyword at the start of a line. This is followed by the name of any output variables, an equals (&lt;code&gt;=&lt;/code&gt;) sign, then the name of the function and any input arguments in parentheses. Within the the function you have to assign to any variables you specified in the definition line as outputs. A simple example MATLAB function is shown below:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;[total] &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;num_1,num_2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total&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;o&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;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you see the &lt;code&gt;function&lt;/code&gt; definition on line 1. There is only one output variable, called &lt;code&gt;total&lt;/code&gt;, for this function. The name of the function is &lt;code&gt;addition&lt;/code&gt; and it takes two arguments, which will be assigned the names &lt;code&gt;num_1&lt;/code&gt; and &lt;code&gt;num_2&lt;/code&gt; in the function body. Line 2 is the implementation of the function. The value of &lt;code&gt;total&lt;/code&gt; is set equal to the sum of &lt;code&gt;num_1&lt;/code&gt; and &lt;code&gt;num_2&lt;/code&gt;. The last line of the function is the &lt;code&gt;end&lt;/code&gt; keyword that tells the MATLAB interpreter the definition of the function has finished.&lt;/p&gt;
&lt;p&gt;To use this function in MATLAB, you should save it in a file called &lt;code&gt;addition.m&lt;/code&gt;, matching the name of the function. Alternatively, it can be placed in file with other commands provided that the function definition is the last thing in the file and the file is &lt;em&gt;not&lt;/em&gt; named &lt;code&gt;addition.m&lt;/code&gt;. Then, you can run the function by typing the following code in the MATLAB console:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_1&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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_2&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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum_of_vars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;sum_of_vars =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have defined two variables called &lt;code&gt;var_1&lt;/code&gt; and &lt;code&gt;var_2&lt;/code&gt; that hold the values 20 and 10, respectively. Then you created a third variable called &lt;code&gt;sum_of_vars&lt;/code&gt; that stores the output from &lt;code&gt;addition()&lt;/code&gt;. Check out the &lt;em&gt;Variable explorer&lt;/em&gt;, and you&amp;rsquo;ll see that &lt;code&gt;sum_of_vars&lt;/code&gt; has the value 30, as expected. Notice that the name &lt;code&gt;sum_of_vars&lt;/code&gt; did not have to be the same name as the output variable used in the function definition, which was &lt;code&gt;total&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;MATLAB does not require a function to provide an output value. In this case, you would remove the output variable and the equals sign from the function definition. Modify your &lt;code&gt;addition.m&lt;/code&gt; file so that the code looks like this:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&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;hll&quot;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;num_1,num_2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total&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;o&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;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The only change in this code from the earlier code is that you deleted the &lt;code&gt;[total] =&lt;/code&gt; from line 1, the other lines are exactly the same. Now if you try to assign the result of calling this function to a variable, MATLAB will generate an error in the console:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_1&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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_2&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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum_of_vars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Error using addition&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Too many output arguments.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you defined the same two variables &lt;code&gt;var_1&lt;/code&gt; and &lt;code&gt;var_2&lt;/code&gt; as before and called &lt;code&gt;addition()&lt;/code&gt; in the same way as before. However, since &lt;code&gt;addition()&lt;/code&gt; no longer specifies an output variable, MATLAB generates an error message that there are too many output arguments. Clicking on the word &lt;code&gt;addition&lt;/code&gt; will open the definition of the function for you to edit or view the source code to fix the problem.&lt;/p&gt;
&lt;p&gt;In Python, the &lt;code&gt;def&lt;/code&gt; keyword starts a function definition. The &lt;code&gt;def&lt;/code&gt; keyword must be followed by the name of the function and any arguments to the function inside parentheses, similar to MATLAB. The line with &lt;code&gt;def&lt;/code&gt; must be ended with a colon (&lt;code&gt;:&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Starting on the next line, the code that should be executed as part of the function must be indented one level. In Python, the function definition ends when a line of code starts at the same indentation level as the &lt;code&gt;def&lt;/code&gt; keyword on the first line.&lt;/p&gt;
&lt;p&gt;If your function returns some output back to the caller, Python does not require that you specify a name for an output variable. Instead, you use the &lt;code&gt;return&lt;/code&gt; statement to send an output value from the function.&lt;/p&gt;
&lt;p&gt;An equivalent function in Python to your first &lt;code&gt;addition()&lt;/code&gt; example with an output variable is shown below:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addition&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;n&quot;&gt;num_2&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;n&quot;&gt;total&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;lineno&quot;&gt; 3 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you see the &lt;code&gt;def&lt;/code&gt; keyword followed by the function name and the two arguments &lt;code&gt;num_1&lt;/code&gt; and &lt;code&gt;num_2&lt;/code&gt; on line 1. On line 2 you can see the creation of a new variable &lt;code&gt;total&lt;/code&gt; to store the sum of &lt;code&gt;num_1&lt;/code&gt; and &lt;code&gt;num_2&lt;/code&gt;, and on line 3 the value of &lt;code&gt;total&lt;/code&gt; is returned to the point where this function was called. Notice that lines 2 and 3 are indented by 4 spaces because they make up the body of the function.&lt;/p&gt;
&lt;p&gt;The variable that stores the sum of &lt;code&gt;num_1&lt;/code&gt; and &lt;code&gt;num_2&lt;/code&gt; can have any name, it doesn&amp;rsquo;t have to be called &lt;code&gt;total&lt;/code&gt;. In fact, you don&amp;rsquo;t need to create a variable there at all. You can simplify your previous function definition by eliminating &lt;code&gt;total&lt;/code&gt; and simply returning the value of &lt;code&gt;num_1 + num_2&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; 1 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addition&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;n&quot;&gt;num_2&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;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;return&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_1&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Line 1 in this code is the same as it was before, you have only changed line 2 and deleted line 3. Line 2 now computes the value of &lt;code&gt;num_1 + num_2&lt;/code&gt; and returns that value back to the caller of the function. Line 2 is indented by 4 spaces because it makes up the body of the function.&lt;/p&gt;
&lt;p&gt;To use this function in Python, you do not need to save it in a file with a special name. You can place the function definition in any Python file, at any point in the file. There is no restriction that the function definition has to be last. In fact, you can even define functions right from the console, which is not possible in MATLAB.&lt;/p&gt;
&lt;p&gt;Open Spyder and in the Console pane type:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addition&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;n&quot;&gt;num_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On this line of code you are creating the function definition. In the Spyder/IPython console, once you start a function definition and press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;, the start of the line becomes three dots and the cursor is automatically indented. Now you can type the remainder of the function definition. You&amp;rsquo;ll have to press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; twice to complete the definition:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addition&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;n&quot;&gt;num_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;k&quot;&gt;return&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;gp&quot;&gt;   ...:&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have the definition of the function on the first line and the body of the function on the second line. The console automatically adds the &lt;code&gt;...:&lt;/code&gt; at the start of the lines to indicate these are &lt;strong&gt;continuation lines&lt;/strong&gt; that apply to the function definition.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve completed the definition, you can execute the function from the console as well. You should type this 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;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_2&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;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum_of_vars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum_of_vars&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[5]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you first create two variables &lt;code&gt;var_1&lt;/code&gt; and &lt;code&gt;var_2&lt;/code&gt; that store the values you want to add together. Then, on input line 4, you assign &lt;code&gt;sum_of_vars&lt;/code&gt; to the result that is returned from &lt;code&gt;addition()&lt;/code&gt;. On input line 5, you are outputting the value of &lt;code&gt;sum_of_vars&lt;/code&gt; to the console screen. This displays 30, the sum of 10 and 20.&lt;/p&gt;
&lt;p&gt;In Python, if you do not explicitly put a &lt;code&gt;return&lt;/code&gt; statement, your function will implicitly return the special value &lt;code&gt;None&lt;/code&gt;. You should change your Python definition of &lt;code&gt;addition()&lt;/code&gt; to see how this works. In the Spyder/IPython console, type the following:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [6]: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addition&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;n&quot;&gt;num_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;gp&quot;&gt;   ...: &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;total&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&gt;&lt;span class=&quot;gp&quot;&gt;   ...:&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have the same &lt;code&gt;def&lt;/code&gt; line on input line 6. You have changed the first continuation line to assign the result of the addition to &lt;code&gt;total&lt;/code&gt; instead of returning. Now you should see what happens when we execute this modified 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;In [7]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum_of_vars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [8]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum_of_vars&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [9]:&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, on input line 7 you are assigning &lt;code&gt;sum_of_vars&lt;/code&gt; to be the returned value from &lt;code&gt;addition()&lt;/code&gt;. Then, on input line 8, you are showing the value of &lt;code&gt;sum_of_vars&lt;/code&gt; on the console screen, just like before. This time though, there is no output! By default, Python prints nothing when it outputs a variable whose value is &lt;code&gt;None&lt;/code&gt;. You can double check the value of the &lt;code&gt;sum_of_vars&lt;/code&gt; variable by looking at the &lt;em&gt;Variable explorer&lt;/em&gt;. In the &lt;em&gt;Type&lt;/em&gt; column, it should list &lt;code&gt;NoneType&lt;/code&gt;, telling you that &lt;code&gt;sum_of_vars&lt;/code&gt; is the special &lt;code&gt;None&lt;/code&gt; value.&lt;/p&gt;
&lt;h4 id=&quot;functions-accept-positional-and-keyword-arguments-in-python&quot;&gt;Functions Accept Positional and Keyword Arguments in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, functions have input arguments specified on the first line, in the &lt;code&gt;function&lt;/code&gt; definition. When you call a function in MATLAB, you can pass from zero up to the number of arguments that are specified. In the body of the function, you can check the number of input arguments the caller actually passed to execute different code. This is useful when you want different arguments to have different meaning, like in the example below:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;[result] &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addOrSubtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;num_1,num_2,subtract&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;% ADDORSUBTRACT  Add or subtract two value&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;%   RESULT = addOrSubtract(NUM_1,NUM_2) adds NUM_1 and NUM_2 together&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;%&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;%   RESULT = addOrSubtract(NUM_1,NUM_2,true) subtracts NUM_2 from NUM_1&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;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargin&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;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;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;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;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;otherwise&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &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;mi&quot;&gt;0&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;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are defining a function with three possible input arguments. On line 7, you are starting a &lt;code&gt;switch&lt;/code&gt;/&lt;code&gt;case&lt;/code&gt; block that determines how many input arguments were passed to the function by using the &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/nargin.html&quot;&gt;special variable &lt;code&gt;nargin&lt;/code&gt;&lt;/a&gt;. This variable stores the actual number of arguments the caller passed into the function.&lt;/p&gt;
&lt;p&gt;In your code above, you are defining three cases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If the number of input arguments is 2, you are adding &lt;code&gt;num_1&lt;/code&gt; and &lt;code&gt;num_2&lt;/code&gt; together.&lt;/li&gt;
&lt;li&gt;If the number of input arguments is 3, you are subtracting &lt;code&gt;num_2&lt;/code&gt; from &lt;code&gt;num_1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If fewer than 2 arguments are passed, the output will be &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If more than 3 arguments are passed, MATLAB will raise an error.&lt;/p&gt;
&lt;p&gt;Now you should experiment with this function. Save the code above into a file called &lt;code&gt;addOrSubtract.m&lt;/code&gt; and then on the MATLAB console, try the version with two input arguments:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addOrSubtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are calling &lt;code&gt;addOrSubtract()&lt;/code&gt; with two arguments, so the arguments are added together, resulting in an answer of &lt;code&gt;30&lt;/code&gt;. Next, try calling &lt;code&gt;addOrSubtract()&lt;/code&gt; with three arguments:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addOrSubtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   -10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you used three input arguments, and found that the second argument was subtracted from the first, resulting in an answer of &lt;code&gt;-10&lt;/code&gt;. Third, try calling &lt;code&gt;addOrSubtract()&lt;/code&gt; with one argument:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addOrSubtract&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;ans =&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;     0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you used one input argument and found the answer was 0, because MATLAB only found one argument to the function and used the &lt;code&gt;otherwise&lt;/code&gt; case. Finally, try calling &lt;code&gt;addOrSubtract()&lt;/code&gt; with four arguments:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addOrSubtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;true&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;go&quot;&gt;Error using addOrSubtract&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Too many input arguments.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you find that MATLAB raises an error because there were more input arguments passed than were defined in the &lt;code&gt;function&lt;/code&gt; line.&lt;/p&gt;
&lt;p&gt;There are four key takeaways from this example with MATLAB:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There is only one kind of argument in a function definition.&lt;/li&gt;
&lt;li&gt;The meaning of an argument in the code is determined by its position in the function definition.&lt;/li&gt;
&lt;li&gt;The maximum number of arguments that can be passed to a function is determined by the number of arguments specified in the function definition.&lt;/li&gt;
&lt;li&gt;Any number of arguments up to the maximum can be passed by the caller.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In Python, there are two kinds of arguments you can specify when defining a function. These are &lt;strong&gt;required&lt;/strong&gt; and &lt;strong&gt;optional&lt;/strong&gt; arguments. The key difference between these is that required arguments must be passed when a function is called, while optional are given a default value in the function definition.&lt;/p&gt;
&lt;p&gt;You can see the differences between these two styles in the next example:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_or_subtract&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;n&quot;&gt;num_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subtract&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;lineno&quot;&gt; 2 &lt;/span&gt;    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Add or subtract two numbers, depending on the value of subtract.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subtract&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;return&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;lineno&quot;&gt; 5 &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; 6 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are defining a function called &lt;code&gt;add_or_subtract()&lt;/code&gt; that has three arguments: &lt;code&gt;num_1&lt;/code&gt;, &lt;code&gt;num_2&lt;/code&gt;, and &lt;code&gt;subtract&lt;/code&gt;. In the function definition, you can see the two types of arguments. The first two arguments, &lt;code&gt;num_1&lt;/code&gt; and &lt;code&gt;num_2&lt;/code&gt;, are required arguments.&lt;/p&gt;
&lt;p&gt;The third argument, &lt;code&gt;subtract&lt;/code&gt;, has a default value assigned to it by specifying a value after an equals sign in the function definition. This means that when the function is called, passing a value for &lt;code&gt;subtract&lt;/code&gt; is optional. If no value is passed, the default as defined in the function definition line will be used. In this case, the default value is &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the body of the function, you are testing the value of &lt;code&gt;subtract&lt;/code&gt; with the &lt;code&gt;if&lt;/code&gt; statement to determine whether addition or subtraction should be performed. If &lt;code&gt;subtract&lt;/code&gt; is &lt;code&gt;True&lt;/code&gt;, &lt;code&gt;num_2&lt;/code&gt; will be subtracted from &lt;code&gt;num_1&lt;/code&gt;. Otherwise, if &lt;code&gt;subtract&lt;/code&gt; is &lt;code&gt;False&lt;/code&gt;, then &lt;code&gt;num_1&lt;/code&gt; will be added to &lt;code&gt;num_2&lt;/code&gt;. In either case, the result of the arithmetic operation will be returned to the caller.&lt;/p&gt;
&lt;p&gt;In addition to the two types of arguments you can use when &lt;strong&gt;defining&lt;/strong&gt; a function, there are two kinds of arguments you can specify when &lt;strong&gt;calling&lt;/strong&gt; a function. These are called &lt;strong&gt;positional&lt;/strong&gt; and &lt;a href=&quot;https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments&quot;&gt;&lt;strong&gt;keyword&lt;/strong&gt;&lt;/a&gt; arguments. You can see the difference between these in the following example. First, try passing only two arguments to the 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;In [1]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_or_subtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[1]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you passed only two arguments to &lt;code&gt;add_or_subtract()&lt;/code&gt;, &lt;code&gt;10&lt;/code&gt; and &lt;code&gt;20&lt;/code&gt;. In this case, you passed these values as positional arguments, and the meaning of the arguments is defined by their position in the function call.&lt;/p&gt;
&lt;p&gt;Since only the two required arguments were passed, &lt;code&gt;subtract&lt;/code&gt; will take on the default value, which is &lt;code&gt;False&lt;/code&gt;. Therefore, 10 and 20 will be added together, which you can see on the output line. Next, try passing a value for &lt;code&gt;subtract&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;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_or_subtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&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;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_or_subtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&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;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;-10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you passed three arguments to &lt;code&gt;add_or_subtract()&lt;/code&gt;, with two different values for the &lt;code&gt;subtract&lt;/code&gt; argument. First, you passed &lt;code&gt;False&lt;/code&gt; on input line 2. The result was the addition of 10 and 20. Then, you passed &lt;code&gt;True&lt;/code&gt; on input line 3, resulting in the difference between 10 and 20, or -10.&lt;/p&gt;
&lt;p&gt;In these examples, you saw that it is possible in Python to define default values for arguments to a function. This means when you call the function, any arguments with default values are optional and do not have to be passed. If no value is passed for any default arguments, the default value will be used. However, you &lt;em&gt;must&lt;/em&gt; pass a value for every argument without a default value. Otherwise, Python will raise an error:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_or_subtract&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;Traceback (most recent call last):&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  File &amp;quot;&amp;lt;ipython-input-4-f9d1f2ae4494&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    add_or_subtract(10)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;TypeError: add_or_subtract() missing 1 required positional argument: &amp;#39;num_2&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have only passed one of the two required arguments to &lt;code&gt;add_or_subtract()&lt;/code&gt;, so Python raises a &lt;code&gt;TypeError&lt;/code&gt;. The error message tells you that you did not pass a value for &lt;code&gt;num_2&lt;/code&gt;, because it does not have a default value.&lt;/p&gt;
&lt;p&gt;In these last three example, you have used &lt;strong&gt;positional&lt;/strong&gt; arguments, so which parameter is assigned to the variables in the function depends on the order they are passed. There is another method to pass arguments to functions in Python, called &lt;strong&gt;keyword&lt;/strong&gt; arguments. To use keyword arguments, you specify the name of the argument in the function call:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_or_subtract&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;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;num_2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subtract&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;gh&quot;&gt;Out[5]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;-10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have used keyword arguments for all three arguments to &lt;code&gt;add_or_subtract()&lt;/code&gt;. Keyword arguments are specified by stating the argument name, then an equals sign, then the value that argument should have. One of the big advantages of keyword arguments is that they make your code more explicit. (As the &lt;em&gt;Zen of Python&lt;/em&gt; says, explicit is better than implicit.) However, they make the code somewhat longer, so it&amp;rsquo;s up to your judgement when to use keyword arguments or not.&lt;/p&gt;
&lt;p&gt;Another benefit of keyword arguments is that they can be specified in any order:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_or_subtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subtract&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;num_2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_1&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;gh&quot;&gt;Out[6]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;-10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have specified the three arguments for &lt;code&gt;add_or_subtract()&lt;/code&gt; as keyword arguments, but the order is different from in the function definition. Nonetheless, Python connects the right variables together because they are specified as keywords instead of positional arguments.&lt;/p&gt;
&lt;p&gt;You can also mix positional and keyword arguments together in the same function call. If positional and keyword arguments are mixed together, the positional arguments &lt;em&gt;must&lt;/em&gt; be specified first, before any keyword 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;In [7]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_or_subtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subtract&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;gh&quot;&gt;Out[7]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;-10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have specified the values for &lt;code&gt;num_1&lt;/code&gt; and &lt;code&gt;num_2&lt;/code&gt; using positional arguments, and the value for &lt;code&gt;subtract&lt;/code&gt; using a keyword argument. This is probably the most common case of using keyword arguments, because it provides a good balance between being explicit and being concise.&lt;/p&gt;
&lt;p&gt;Finally, there is one last benefit of using keyword arguments and default values. Spyder, and other IDEs, provide introspection of function definitions. This will tell you the names of all of the defined function arguments, which ones have default arguments, and the value of the default arguments. This can save you time and make your code easier and faster to read.&lt;/p&gt;
&lt;h4 id=&quot;there-are-no-switchcase-blocks-in-python&quot;&gt;There Are No &lt;code&gt;switch&lt;/code&gt;/&lt;code&gt;case&lt;/code&gt; Blocks in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, you can use &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/switch.html&quot;&gt;&lt;code&gt;switch&lt;/code&gt;/&lt;code&gt;case&lt;/code&gt; blocks&lt;/a&gt; to execute code by checking the value of a variable for equality with some constants. This type of syntax is quite useful when you know you want to handle a few discrete cases. Try out a &lt;code&gt;switch&lt;/code&gt;/&lt;code&gt;case&lt;/code&gt; block with this example:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&quot;&gt;&lt;pre&gt;&lt;span&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;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;otherwise&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;neither&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nor&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you start by defining &lt;code&gt;num&lt;/code&gt; and setting it equal to 10 and on the following lines you test the value of &lt;code&gt;num&lt;/code&gt;. This code will result in the output &lt;code&gt;num is 10&lt;/code&gt; being displayed on the console, since &lt;code&gt;num&lt;/code&gt; is equal to 10.&lt;/p&gt;
&lt;p&gt;This syntax is an interesting comparison of MATLAB vs Python because Python does not have a similar syntax. Instead, you should use an &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;elif&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; block:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num is 10&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;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;num is 20&amp;quot;&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;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;num is neither 10 nor 20&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you start by defining &lt;code&gt;num&lt;/code&gt; and setting it equal to &lt;code&gt;10&lt;/code&gt;. On the next several lines you are writing an &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;elif&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; block to check the different values that you are interested in.&lt;/p&gt;
&lt;h4 id=&quot;namespaces-are-one-honking-great-idea-in-python&quot;&gt;Namespaces Are One Honking Great Idea in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, all functions are found in a single scope. MATLAB has a &lt;a href=&quot;https://www.mathworks.com/help/matlab/matlab_prog/function-precedence-order.html&quot;&gt;defined search order&lt;/a&gt; for finding functions within the current scope. If you define your own function for something that MATLAB already includes, you may get unexpected behavior.&lt;/p&gt;
&lt;p&gt;As you saw in the &lt;em&gt;Zen of Python&lt;/em&gt;, &lt;strong&gt;namespaces&lt;/strong&gt; are one honking great idea. Namespaces are a way to provide different scopes for names of functions, classes, and variables. This means you have to tell Python which library has the function you want to use. This is a good thing, especially in cases where multiple libraries provide the same function.&lt;/p&gt;
&lt;p&gt;For instance, the built-in &lt;code&gt;math&lt;/code&gt; library provides a &lt;a href=&quot;https://realpython.com/python-square-root-function/&quot;&gt;square root function&lt;/a&gt;, as does the more advanced NumPy library. Without namespaces, it would be more difficult to tell Python which square root function you wanted to use.&lt;/p&gt;
&lt;p&gt;To tell Python where a function is located, you first have to &lt;code&gt;import&lt;/code&gt; the library, which creates the namespace for that library&amp;rsquo;s code. Then, when you want to use a function from the library, you tell Python which namespace to look in:&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;In [1]: &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;In [2]: &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;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;2.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, on input line 1 you imported the &lt;code&gt;math&lt;/code&gt; library that is built-in to Python. Then, input line 2 computes the square root of 4 using the square root function from within the &lt;code&gt;math&lt;/code&gt; library. The &lt;code&gt;math.sqrt()&lt;/code&gt; line should be read as &amp;ldquo;from within &lt;code&gt;math&lt;/code&gt;, find &lt;code&gt;sqrt()&lt;/code&gt;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;import&lt;/code&gt; keyword searches for the named library and binds the namespace to the same name as the library by default. You can read more about how Python searches for libraries in &lt;a href=&quot;https://realpython.com/python-modules-packages/&quot;&gt;Python Modules and Packages – An Introduction&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can also tell Python what name it should use for a library. For instance, it is very common to see &lt;code&gt;numpy&lt;/code&gt; shortened to &lt;code&gt;np&lt;/code&gt; with the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sqrt&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;gh&quot;&gt;Out[4]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;2.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, input line 3 imports NumPy and tells Python to put the library into the &lt;code&gt;np&lt;/code&gt; namespace. Then, whenever you want to use a function from NumPy, you use the &lt;code&gt;np&lt;/code&gt; abbreviation to find that function. On input line 4, you are computing the square root of 4 again, but this time, using &lt;code&gt;np.sqrt()&lt;/code&gt;. &lt;code&gt;np.sqrt()&lt;/code&gt; should be read as &amp;ldquo;from within NumPy, find &lt;code&gt;sqrt()&lt;/code&gt;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;There are two main caveats to using namespaces where you should be careful:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;You should not name a variable with the same name as one of the functions built into Python. You can find a complete list of these functions in the &lt;a href=&quot;https://docs.python.org/3/library/functions.html&quot;&gt;Python documentation&lt;/a&gt;. The most common variable names that are also built-in functions and should not be used are &lt;code&gt;dir&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;input&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;sum&lt;/code&gt;, &lt;code&gt;str&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt;, and &lt;code&gt;vars&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You should not name a Python file (one with the extension &lt;code&gt;.py&lt;/code&gt;) with the same name as a library that you have installed. In other words, you should not create a Python file called &lt;code&gt;math.py&lt;/code&gt;. This is because Python searches the current working directory first when it tries to import a library. If you have a file called &lt;code&gt;math.py&lt;/code&gt;, that file will be found before the built-in &lt;code&gt;math&lt;/code&gt; library and you will probably see an &lt;code&gt;AttributeError&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;the-most-recent-unassigned-result-is-available-as-_-in-python&quot;&gt;The Most Recent Unassigned Result Is Available as &lt;code&gt;_&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;The MATLAB console uses &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/ans.html&quot;&gt;&lt;code&gt;ans&lt;/code&gt;&lt;/a&gt; to store the result of the most recent calculation if that result was not assigned to a variable. This is really useful when you forgot to assign the result of a calculation to a variable or when you just want to chain a few simple calculations together. To see the differences between MATLAB vs Python, try out this example:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&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;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    60&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ans&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;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    70&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you use &lt;code&gt;sum()&lt;/code&gt; to calculate the sum of the array. Since there is no equal sign with a variable name on the left, MATLAB assigns the output from &lt;code&gt;sum()&lt;/code&gt; to &lt;code&gt;ans&lt;/code&gt;. You can then use that variable in further calculations, as you do here by adding 10 to the last result. Note that this will only work in the MATLAB console, not in a script file.&lt;/p&gt;
&lt;p&gt;In the Python console (including the IPython/Spyder console), the output from the most recent calculation is stored in &lt;code&gt;_&lt;/code&gt; (the underscore character). Try the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [1]: &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;mi&quot;&gt;10&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;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[1]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;60&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&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;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;70&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you use &lt;code&gt;sum()&lt;/code&gt; to calculate the sum of the list. Since there is no equal sign with a variable name on the left, Python assigns the output from &lt;code&gt;sum()&lt;/code&gt; to the underscore (&lt;code&gt;_&lt;/code&gt;), in addition to printing it on the output line. You can then use that variable in further calculations, as you do here by adding 10 to the last result. Note that this will only work in the Python console, not in a script file.&lt;/p&gt;
&lt;p&gt;In the IPython console, there is one additional feature enabled. You can append a number after the underscore to retrieve the result of any previous line. Try the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;80&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[4]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;90&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code on input line 3 you are using &lt;code&gt;_1&lt;/code&gt; to mean the value of output line 1, the &lt;code&gt;sum()&lt;/code&gt; line. To that result (60) you are adding 20, producing a result of 80. On input line 4, you are adding 20 to the value of output line 2, accessed with &lt;code&gt;_2&lt;/code&gt;, so the result is 90.&lt;/p&gt;
&lt;p&gt;Notice that the Spyder Variable explorer does not show this variable by default, whereas &lt;code&gt;ans&lt;/code&gt; is shown in the MATLAB Variable explorer. In &lt;a href=&quot;#there-are-no-private-properties-or-methods-in-python&quot;&gt;a few sections&lt;/a&gt;, you&amp;rsquo;ll see why the underscore isn&amp;rsquo;t shown by default and how you can see it.&lt;/p&gt;
&lt;h4 id=&quot;anonymous-functions-are-created-with-the-lambda-keyword-in-python&quot;&gt;Anonymous Functions Are Created With the &lt;code&gt;lambda&lt;/code&gt; Keyword in Python&lt;/h4&gt;
&lt;p&gt;MATLAB uses the the at-symbol (&lt;code&gt;@&lt;/code&gt;) to indicate that what follows is the definition of an &lt;a href=&quot;https://www.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html&quot;&gt;anonymous function&lt;/a&gt;. Anonymous functions are functions that are not defined in a program file and do not use the &lt;code&gt;function&lt;/code&gt; keyword. A program file is a MATLAB file with a filename ending in &lt;code&gt;.m&lt;/code&gt;. Anonymous functions are limited to a single statement so they are intended for simple computations.&lt;/p&gt;
&lt;p&gt;You can try out the differences of anonymous functions in MATLAB vs Python with this example:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sayHello&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;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;Hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;%s\n&amp;quot;,x);&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sayHello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;Eleanor&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Hello, Eleanor&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, the first input line defines the anonymous function with one input parameter, &lt;code&gt;x&lt;/code&gt;. The body of the function follows, which uses &lt;code&gt;fprintf()&lt;/code&gt; to format the input into a string. This function is assigned to &lt;code&gt;sayHello&lt;/code&gt;. On the second input line, &lt;code&gt;sayHello()&lt;/code&gt; is executed and passed &lt;code&gt;&quot;Eleanor&quot;&lt;/code&gt; as the value. The result the string &lt;code&gt;Hello, Eleanor&lt;/code&gt; printed on the console.&lt;/p&gt;
&lt;p&gt;Anonymous functions are most often used when you need to pass one function into another function. In these cases, it is often not necessary to assign the function definition to a variable:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;integral&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(@(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.^&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    243&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, the first input line executes &lt;code&gt;integral()&lt;/code&gt;, a function that computes the definite integral of a given function. The first argument to &lt;code&gt;integral()&lt;/code&gt; must be a function, so this is a perfect place to use an anonymous function. Here, your anonymous function squares whatever the input value is. The other two arguments to &lt;code&gt;integral()&lt;/code&gt; are the limits of the integration, such that the result of integrating &lt;code&gt;x.^2&lt;/code&gt; from 0 to 9 is 243.&lt;/p&gt;
&lt;p&gt;Python uses the &lt;code&gt;lambda&lt;/code&gt; keyword to define anonymous functions. Other than this syntax difference, anonymous functions work the same way in Python as in MATLAB:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;say_hello&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;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;Hello, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{x: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;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;say_hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Eleanor&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Hello, Eleanor&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, input line 1 defines the &lt;code&gt;lambda&lt;/code&gt; function with one parameter, &lt;code&gt;x&lt;/code&gt;. You use &lt;code&gt;print()&lt;/code&gt; within the function definition to show an f-string with the value of the input parameter. The function is then stored in &lt;code&gt;say_hello()&lt;/code&gt;. Input line 2 evaluates &lt;code&gt;say_hello()&lt;/code&gt; with the input string &lt;code&gt;&quot;Eleanor&quot;&lt;/code&gt; and produces the &lt;code&gt;Hello, Eleanor&lt;/code&gt; output.&lt;/p&gt;
&lt;p&gt;In Python, the official style guide called PEP 8 &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/#programming-recommendations&quot;&gt;specifically disrecommends&lt;/a&gt; assigning &lt;code&gt;lambda&lt;/code&gt; expressions to variable names, as you saw in the last example. If you want to give a function a name to refer to it several times, the preference is to use the &lt;code&gt;def&lt;/code&gt; syntax and define a full function, even for one-line functions.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;lambda&lt;/code&gt; functions are still useful when they are passed as arguments into another 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;In [3]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scipy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;integrate&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;integrate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quad&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;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;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;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[4]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(243.0, 2.6978419498391304e-12)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, input line 3 imports the &lt;code&gt;scipy.integrate&lt;/code&gt; library and stores it in the &lt;code&gt;integrate&lt;/code&gt; namespace. On input line 4, you are using &lt;a href=&quot;https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.quad.html#scipy.integrate.quad&quot;&gt;&lt;code&gt;quad()&lt;/code&gt; from &lt;code&gt;scipy.integrate&lt;/code&gt;&lt;/a&gt; to compute the integral using quadrature, very similar to &lt;code&gt;integral()&lt;/code&gt; in MATLAB. The first argument to &lt;code&gt;quad()&lt;/code&gt; is the function to be integrated, and you use a &lt;code&gt;lambda&lt;/code&gt; function to specify that &lt;code&gt;x ** 2&lt;/code&gt; should be integrated. The second and third arguments to &lt;code&gt;quad()&lt;/code&gt; specify that the integral should be conducted from 0 to 9.&lt;/p&gt;
&lt;p&gt;You can see that the result on output line 4 has two values, &lt;code&gt;243.0&lt;/code&gt; and &lt;code&gt;2.6978419498391304e-12&lt;/code&gt;. The first value is the result of the integration, and is equal to the result from MATLAB. The second value is an estimate of the absolute error in the result. An error this small is approximately the precision of the numbers used to store the result, so the answer is about as accurate as it can be.&lt;/p&gt;
&lt;p&gt;You can read more about &lt;code&gt;lambda&lt;/code&gt; in &lt;a href=&quot;https://realpython.com/python-lambda/&quot;&gt;How to Use Python lambda Functions&lt;/a&gt; or watch the videos in the &lt;a href=&quot;https://realpython.com/courses/python-lambda-functions/&quot;&gt;How to Use Python Lambda Functions&lt;/a&gt; course.&lt;/p&gt;
&lt;h3 id=&quot;you-will-only-need-these-in-specialized-situations&quot;&gt;You Will Only Need These in Specialized Situations&lt;/h3&gt;
&lt;p&gt;In this section, the examples are more advanced concepts that you will need as you become more advanced in Python development. Some of the examples here deal with developing applications or higher-level code than the other sections. When you see these concepts in other code, you can dig in to them when you feel comfortable.&lt;/p&gt;
&lt;h4 id=&quot;class-definitions-start-with-class-in-python&quot;&gt;Class Definitions Start With &lt;code&gt;class&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;MATLAB has two ways to define a class. With the first way, you can put all of the &lt;a href=&quot;https://www.mathworks.com/help/matlab/matlab_oop/create-a-simple-class.html&quot;&gt;class definition in a single file&lt;/a&gt; with the name of the class as the filename. Then within the file, you can use the &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/classdef.html&quot;&gt;&lt;code&gt;classdef&lt;/code&gt; keyword&lt;/a&gt; to define the properties and methods that belong to the class.&lt;/p&gt;
&lt;p&gt;With the second way, you can &lt;a href=&quot;https://www.mathworks.com/help/matlab/matlab_oop/methods-in-separate-files.html&quot;&gt;create a folder that starts with &lt;code&gt;@&lt;/code&gt;&lt;/a&gt; and has the same name as the class. In that folder, you can create a single file that has the same name as the class. The function definition in that file will be used as the class initializer, and it should call &lt;code&gt;class()&lt;/code&gt; to instantiate the class. Methods of the class can be defined in other files in the same folder, where the name of each file must be the same as the name of the method.&lt;/p&gt;
&lt;p&gt;Python only has one way to define a class, using the &lt;a href=&quot;https://docs.python.org/3/tutorial/classes.html&quot;&gt;&lt;code&gt;class&lt;/code&gt; keyword&lt;/a&gt;. Since Python uses indentation to find the end of the class definition, the entire definition must be contained in a single file:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# The rest of the class definition goes here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, the first line defines the name of the class. It starts with the &lt;code&gt;class&lt;/code&gt; keyword, followed by the name of the class and a colon. Underneath this line, all of the code that is part of the class definition (methods and attributes) must be indented. Once a line of code starts in the same column as the &lt;code&gt;c&lt;/code&gt; in &lt;code&gt;class&lt;/code&gt;, the class definition will be ended.&lt;/p&gt;
&lt;p&gt;The second line in this code is a comment to note that the rest of the class definition would follow the &lt;code&gt;class&lt;/code&gt; line.&lt;/p&gt;
&lt;p&gt;As in all object-oriented code, Python classes can inherit from superclasses. The superclass of a given class can be given as a parameter in the class definition, as shown below:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MySuperClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# The rest of the class definition goes here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, the only change is that the name of the superclass is listed inside round brackets before the colon.&lt;/p&gt;
&lt;h4 id=&quot;there-are-no-private-properties-or-methods-in-python&quot;&gt;There Are No Private Properties or Methods in Python&lt;/h4&gt;
&lt;p&gt;MATLAB allows class properties and method to be set as one of four &lt;a href=&quot;https://www.mathworks.com/help/matlab/matlab_oop/method-attributes.html&quot;&gt;&lt;code&gt;Access&lt;/code&gt; options&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;public&lt;/code&gt;&lt;/strong&gt;: Access to the property or method is unrestricted.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;protected&lt;/code&gt;&lt;/strong&gt;: Access to the property or method is only allowed in this class or subclasses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;private&lt;/code&gt;&lt;/strong&gt;: Access to the property or method is only allowed in this class.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;meta.class&lt;/code&gt; or &lt;code&gt;{meta.class}&lt;/code&gt;&lt;/strong&gt;: Access to the property or method is only allowed in the listed class or classes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This allows you to specifically control the ways that a property or class method can be accessed.&lt;/p&gt;
&lt;p&gt;In Python, there is no way to set a class or instance attribute or method as protected or private. All classes and class instances can have their attributes and methods changed at runtime. Python&amp;rsquo;s convention is that attributes and methods that start with an underscore (&lt;code&gt;_&lt;/code&gt;) are intended to be private, or at least non-public. However, this convention is not enforced by any checks in the language and all attributes and methods can be modified by the user at runtime.&lt;/p&gt;
&lt;p&gt;As you saw in the section about &lt;a href=&quot;#the-most-recent-unassigned-result-is-available-as-_-in-python&quot;&gt;using the underscore to retrieve values in the console&lt;/a&gt;, the underscore is not visible by default in the Spyder &lt;em&gt;Variable explorer&lt;/em&gt;. This is because Spyder and other tools respect the convention that underscore indicates something should be non-public. However, underscores can be shown in the Spyder Variable explorer if you click the gear icon in the top right of that pane and uncheck the &lt;em&gt;Exclude private variables&lt;/em&gt; item. This will also show other non-public variables as well.&lt;/p&gt;
&lt;p&gt;Python uses several special methods that start with a double-underscore (&lt;code&gt;__&lt;/code&gt;), called &lt;strong&gt;dunder methods&lt;/strong&gt;, to implement specific behavior for classes. The most commonly used dunder method is &lt;code&gt;__init__()&lt;/code&gt;, which is the class initializer or constructor. You can read a lot more about dunder methods in &lt;a href=&quot;https://dbader.org/blog/python-dunder-methods&quot;&gt;Enriching Your Python Classes With Dunder (Magic, Special) Methods&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want more information about Python&amp;rsquo;s classes, you can read &lt;a href=&quot;https://realpython.com/oop-in-python-vs-java/&quot;&gt;Object-Oriented Programming in Python vs Java&lt;/a&gt;. Even though that article is about Java, Java is similar to the MATLAB OOP paradigm in terms of the nature of attributes and methods.&lt;/p&gt;
&lt;h4 id=&quot;a-class-refers-to-itself-as-self-in-python&quot;&gt;A Class Refers to Itself as &lt;code&gt;self&lt;/code&gt; in Python&lt;/h4&gt;
&lt;p&gt;MATLAB uses the name &lt;code&gt;obj&lt;/code&gt; when a class wants to refer to the current instance of itself. The &lt;code&gt;obj&lt;/code&gt; should be the first argument passed to an &lt;a href=&quot;https://www.mathworks.com/help/matlab/matlab_oop/ordinary-methods.html&quot;&gt;ordinary method&lt;/a&gt;. MATLAB also defines &lt;a href=&quot;https://www.mathworks.com/help/matlab/matlab_oop/static-methods.html&quot;&gt;static methods&lt;/a&gt; that have no reference to the class instance.&lt;/p&gt;
&lt;p&gt;Python uses the name &lt;code&gt;self&lt;/code&gt; when a class wants to refer to the current instance of itself, but this is actually only a convention. You can call the first argument to an &lt;strong&gt;instance method&lt;/strong&gt; any name you want, but &lt;code&gt;self&lt;/code&gt; is the most common convention. Python also defines static methods that don&amp;rsquo;t take an argument of the class instance and class methods that take an argument of the class object instead of the instance. You can read more about instance, static, and class methods in &lt;a href=&quot;https://realpython.com/instance-class-and-static-methods-demystified/&quot;&gt;Python&amp;rsquo;s Instance, Class, and Static Methods Demystified&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;there-is-one-string-type-in-python&quot;&gt;There Is One String Type in Python&lt;/h4&gt;
&lt;p&gt;In MATLAB, strings of characters are stored in &lt;strong&gt;string arrays&lt;/strong&gt; when you use double quotes (&lt;code&gt;&quot;&lt;/code&gt;) or in &lt;strong&gt;character arrays&lt;/strong&gt; if you use single quotes (&lt;code&gt;&#39;&lt;/code&gt;). If you use both single and double quotes in an array assignment, the array will be promoted to a string array.&lt;/p&gt;
&lt;p&gt;In character arrays, each character in the string occupies one column in the array. For multidimensional character arrays, each row of the array must have the same number of characters, which is to say, the same number of columns. This is shown in the example below:&lt;/p&gt;
&lt;div class=&quot;highlight matlab repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;charArray&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;s&quot;&gt;&amp;#39;Real&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;Python&amp;#39;&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;go&quot;&gt;Dimensions of arrays being concatenated are not consistent.&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;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;charArray&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;s&quot;&gt;&amp;#39;MATLAB&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;Python&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;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;charArray&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;go&quot;&gt;ans =&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;go&quot;&gt;     2     6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, line 1 shows an attempt to define a 2-row character array using single quotes. However, the number of characters in &lt;code&gt;Real&lt;/code&gt; is not the same as in &lt;code&gt;Python&lt;/code&gt;, so MATLAB shows an error message that the dimensions are not consistent.&lt;/p&gt;
&lt;p&gt;On line 4, you successfully create a character array, and on the third input line you are checking the size of the array. The output shows that there are 2 rows, as expected, and 6 columns, since the length of both &lt;code&gt;MATLAB&lt;/code&gt; and &lt;code&gt;Python&lt;/code&gt; are 6 characters.&lt;/p&gt;
&lt;p&gt;This is not the case for string arrays. In string arrays, each string occupies one column in the array and each row in a multidimensional array must have the same number of strings, although each string can have different length. This is shown in the example below:&lt;/p&gt;
&lt;div class=&quot;highlight matlab repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stringArray&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;Real&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &amp;quot;&lt;span class=&quot;n&quot;&gt;Python&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &amp;quot;&lt;span class=&quot;n&quot;&gt;Real&lt;/span&gt;&amp;quot;&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;go&quot;&gt;Error using vertcat&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;Dimensions of arrays being concatenated are not consistent.&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stringArray&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&amp;quot;&lt;span class=&quot;n&quot;&gt;Real&lt;/span&gt;&amp;quot;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &amp;quot;&lt;span class=&quot;n&quot;&gt;Python&lt;/span&gt;&amp;quot;&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;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stringArray&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;go&quot;&gt;ans =&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;go&quot;&gt;     2     1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, line 1 shows an attempt to define a 2-row string array using double quotes. However, the number of strings on the first row (2) does not match the number of strings in the second row (1), so MATLAB raises an error.&lt;/p&gt;
&lt;p&gt;On line 5, you successfully create a string array. Notice that even though the number of characters is different between &lt;code&gt;Real&lt;/code&gt; and &lt;code&gt;Python&lt;/code&gt;, MATLAB is able to create the string array. On line 6 you are checking the size of the string array, which shows that there are 2 rows and 1 column, as expected.&lt;/p&gt;
&lt;p&gt;In Python, there is only one string literal type, called &lt;code&gt;str&lt;/code&gt;. You can create a string literal using single quotes (&lt;code&gt;&#39;&lt;/code&gt;) or double quotes (&lt;code&gt;&quot;&lt;/code&gt;), there is no difference between the two definitions. However, there are some good arguments to prefer double quotes when defining string literals in Python, which are well expressed by the &lt;a href=&quot;https://black.readthedocs.io/en/stable/the_black_code_style.html#strings&quot;&gt;Black code formatting library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is one additional way to define strings in Python, using triple-single-quotes (&lt;code&gt;&#39;&#39;&#39;&lt;/code&gt;) or triple-double-quotes (&lt;code&gt;&quot;&quot;&quot;&lt;/code&gt;). This method of creating strings allows the strings to be defined across multiple lines with the newline characters retained. You can see an example of this in the section about &lt;a href=&quot;#comments-start-with-in-python&quot;&gt;comments and docstrings&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can read a lot more about defining strings in &lt;a href=&quot;https://realpython.com/python-data-types/#strings&quot;&gt;Basic Data Types in Python&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-strings/&quot;&gt;Strings and Character Data in Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can generate similar data structures to the string arrays and character arrays in MATLAB using NumPy in Python. NumPy has several data types, or &lt;strong&gt;dtypes&lt;/strong&gt;, that are related to strings. In Python 3, the default string dtype for arrays is a fixed-width Unicode 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;In [1]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Real&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([&amp;#39;Real&amp;#39;, &amp;#39;Python&amp;#39;], dtype=&amp;#39;&amp;lt;U6&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are importing the NumPy library on input line 1 and assigning it to the &lt;code&gt;np&lt;/code&gt; abbreviation. On input line 2, you are creating a NumPy &lt;code&gt;array&lt;/code&gt; with 2 string elements, &lt;code&gt;Real&lt;/code&gt; and &lt;code&gt;Python&lt;/code&gt;, and assigning the array to &lt;code&gt;arr&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On input line 3, you are showing the value of &lt;code&gt;arr&lt;/code&gt;. The output from the third line shows that &lt;code&gt;arr&lt;/code&gt; is storing an &lt;code&gt;array&lt;/code&gt; that has 2 elements, &lt;code&gt;&#39;Real&#39;&lt;/code&gt; and &lt;code&gt;&#39;Python&#39;&lt;/code&gt;, as expected. Notice that although you defined the array with double-quote strings, Python is displaying them with single-quote strings. Remember that there is no difference between single and double quotes in Python.&lt;/p&gt;
&lt;p&gt;Output line 3 also shows the dtype of the data in the array. For this array, the dtype is &lt;code&gt;&amp;lt;U6&lt;/code&gt;. The three characters here represent the aspects of how the strings are arranged in memory. The &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html#index-6&quot;&gt;&lt;code&gt;&amp;lt;&lt;/code&gt; means that&lt;/a&gt; the byte order of the array is &lt;a href=&quot;https://docs.scipy.org/doc/numpy/glossary.html#term-little-endian&quot;&gt;little endian&lt;/a&gt;. The &lt;code&gt;U&lt;/code&gt; means the string is &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html#index-6&quot;&gt;of the Unicode type&lt;/a&gt;. Finally, the &lt;code&gt;6&lt;/code&gt; means the maximum length of an element is 6 characters. This was chosen as the length of the longest string in the input.&lt;/p&gt;
&lt;p&gt;Notice that the string &lt;code&gt;Real&lt;/code&gt; only has 4 characters. In NumPy string dtype arrays, elements can have fewer than the maximum number of characters without problems, but assigning to elements with strings that are longer than the maximum length will truncate the input:&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;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My favorite language is Python&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[5]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([&amp;#39;My fav&amp;#39;, &amp;#39;Python&amp;#39;], dtype=&amp;#39;&amp;lt;U6&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are attempting to reassign the first element of the array with the string &lt;code&gt;My favorite language is Python&lt;/code&gt;. Clearly, this string is longer than 6 characters, so it is truncated to only 6 when it is assigned, &lt;code&gt;My fav&lt;/code&gt;. (The space counts as 1 character.)&lt;/p&gt;
&lt;p&gt;If you want to create an array that can hold strings of any length, you should pass the &lt;code&gt;object&lt;/code&gt; dtype when you create the array:&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;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Real&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [7]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[7]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([&amp;#39;Real&amp;#39;, &amp;#39;Python&amp;#39;], dtype=object)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating a new array, &lt;code&gt;arr_2&lt;/code&gt;, with two elements again, but this time you specified the dtype to be &lt;code&gt;object&lt;/code&gt;, which you confirmed by showing the output on the console. Now you should see how the &lt;code&gt;object&lt;/code&gt; dtype affects assigning long strings to an element:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [8]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My favorite language is Python&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [9]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[9]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([&amp;#39;My favorite language is Python&amp;#39;, &amp;#39;Python&amp;#39;], dtype=object)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are again assigning the first element of the array to have the value &lt;code&gt;My favorite language is Python&lt;/code&gt;. You can see from the output line that that string is stored as the first element of the array without truncation, because the dtype is &lt;code&gt;object&lt;/code&gt;. The disadvantage of using the &lt;code&gt;object&lt;/code&gt; dtype is that it is usually much slower than the more specific &lt;code&gt;U&lt;/code&gt; dtype, because it has to create a a whole Python object for each element rather than just a NumPy-optimized Unicode object.&lt;/p&gt;
&lt;p&gt;One other difference you will notice from MATLAB is how the shape or size of the array is determined:&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;In [10]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[10]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(2,)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [11]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[11]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(2,)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, we are printing the shape of &lt;code&gt;arr&lt;/code&gt; and &lt;code&gt;arr_2&lt;/code&gt;. Notice that they both have the same shape, two elements in a one-dimensional array. This is similar to the string array from MATLAB, where each string counts as one element in the array. However, the fact that NumPy arrays with the &lt;code&gt;U&lt;/code&gt; dtype have a fixed maximum size behaves more like the character array from MATLAB. You&amp;rsquo;ll see more about differences in how MATLAB and NumPy compute the shape of arrays &lt;a href=&quot;#one-dimensional-arrays-are-vectors-in-numpy&quot;&gt;in a later section&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;libraries-are-not-automatically-reloaded-in-python&quot;&gt;Libraries Are Not Automatically Reloaded in Python&lt;/h4&gt;
&lt;p&gt;When executing a function or script, MATLAB will always use the most up-to-date copy of the file on the disk. Therefore, as you&amp;rsquo;re developing a script, you can run it in the console many times and new changes that you make will automatically be picked up.&lt;/p&gt;
&lt;p&gt;Python operates somewhat differently. Remember that when you want to access code from a file, you have to &lt;code&gt;import&lt;/code&gt; it into a namespace. When Python imports a file or module, it only reads the code the first time it is imported. This saves quite a bit of time if you&amp;rsquo;re importing the same file several times. However, if you&amp;rsquo;re testing your code in the interactive console prompt as you work on it, Python will not pick up any changes if you &lt;code&gt;import&lt;/code&gt; it again.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re developing a module, you have a few options to have Python reload your code when it is imported. If you&amp;rsquo;re using the Spyder IDE, this is not a problem at all, since Spyder has an automatic &lt;a href=&quot;https://docs.spyder-ide.org/ipythonconsole.html#using-umr-to-reload-changed-modules&quot;&gt;User Module Reloading&lt;/a&gt; feature enabled by default.&lt;/p&gt;
&lt;p&gt;Otherwise, if you&amp;rsquo;re using the IPython console outside of Spyder, or the Jupyter Notebook, you can use a magic command defined in those interpreters called &lt;a href=&quot;https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html&quot;&gt;&lt;code&gt;autoreload&lt;/code&gt;&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;In [1]: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;load_ext&lt;/span&gt; autoreload
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;autoreload&lt;/span&gt; 2
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are using the &lt;code&gt;load_ext&lt;/code&gt; magic command to load the &lt;code&gt;autoreload&lt;/code&gt; extension. In IPython and Jupyter Notebooks, commands prefixed with the percent sign &lt;code&gt;%&lt;/code&gt; are magic commands. The &lt;code&gt;autoreload&lt;/code&gt; extension defines the &lt;code&gt;autoreload&lt;/code&gt; magic function, which you use on input line 2. You are passing the parameter &lt;code&gt;2&lt;/code&gt; to the &lt;code&gt;autoreload&lt;/code&gt; magic function, which means that all modules should be reloaded every time a line of code is executed.&lt;/p&gt;
&lt;h2 id=&quot;an-overview-of-basic-array-operations&quot;&gt;An Overview of Basic Array Operations&lt;/h2&gt;
&lt;p&gt;As you have seen, Python does not include a high-speed library for arrays in its standard library. However, the excellent NumPy library is easily available if you install Anaconda. NumPy functions as the &lt;em&gt;de facto&lt;/em&gt; array and matrix library for Python.&lt;/p&gt;
&lt;p&gt;NumPy has two array-like types:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;numpy.ndarray&lt;/code&gt;, also known as &lt;code&gt;numpy.array&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;numpy.matrix&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The main difference between these two types is that the &lt;code&gt;ndarray&lt;/code&gt; can be any number of dimensions, while the &lt;code&gt;matrix&lt;/code&gt; is limited to exactly two dimensions. For &lt;code&gt;ndarray&lt;/code&gt;, all operations such as addition, subtraction, multiplication, exponentiation, and division operate element-wise. However, for the &lt;code&gt;matrix&lt;/code&gt; type, operations like multiplication and exponentiation are matrix operations.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re converting from MATLAB, the &lt;code&gt;matrix&lt;/code&gt; type may seem more familiar. It offers similar behavior that you may be used to from MATLAB in terms of operation syntax. However, NumPy &lt;a href=&quot;https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html#array-or-matrix-which-should-i-use&quot;&gt;strongly recommends&lt;/a&gt; that you use the &lt;code&gt;ndarray&lt;/code&gt; type because it is more flexible and because &lt;code&gt;matrix&lt;/code&gt; will eventually be removed.&lt;/p&gt;
&lt;p&gt;In the rest of this section, you will get to know the major differences between MATLAB and NumPy arrays. You can go in-depth on how to use NumPy arrays by reading &lt;a href=&quot;https://realpython.com/numpy-array-programming/&quot;&gt;Look Ma, No For-Loops: Array Programming With NumPy&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;basic-mathematical-operators-work-element-wise-in-numpy&quot;&gt;Basic Mathematical Operators Work Element-Wise in NumPy&lt;/h3&gt;
&lt;p&gt;MATLAB, with its heritage as a matrix scripting language, assumes that all arithmetic operators will be operating on arrays. Therefore, MATLAB treats the multiplication of matrices or vectors as matrix multiplication. Consider this example:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&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;mi&quot;&gt;5&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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Error using  *&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Incorrect dimensions for matrix multiplication. Check that the number of&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;columns in the first matrix matches the number of rows in the second&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;matrix. To perform elementwise multiplication, use &amp;#39;.*&amp;#39;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating two 1x3 matrices, &lt;code&gt;arr_1&lt;/code&gt;, and &lt;code&gt;arr_2&lt;/code&gt;. Then, you are attempting to multiply them together. For these 1xN arrays, this is equivalent to taking the dot or scalar product. However, the scalar product only works when the left operand is 1xN and the right is Nx1, so MATLAB produces an error message and suggests the dot-star operator (&lt;code&gt;.*&lt;/code&gt;) as the proper syntax for element-wise multiplication:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     4    10    18&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are performing the element-wise multiplication of &lt;code&gt;arr_1&lt;/code&gt; and &lt;code&gt;arr_2&lt;/code&gt;. This multiplies the first element of &lt;code&gt;arr_1&lt;/code&gt; with the first element of &lt;code&gt;arr_2&lt;/code&gt; (&lt;code&gt;4*1 = 4&lt;/code&gt;), second with second (&lt;code&gt;2*5 = 10&lt;/code&gt;), and third with third (&lt;code&gt;3*6 = 18&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;To perform the scalar product, you can take the transpose of &lt;code&gt;arr_2&lt;/code&gt; to convert it to a 3x1 array:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    32&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are performing matrix multiplication with &lt;code&gt;arr_1&lt;/code&gt; and the transpose of &lt;code&gt;arr_2&lt;/code&gt;. Note that you can use either &lt;code&gt;transpose()&lt;/code&gt; or the quote operator (&lt;code&gt;&#39;&lt;/code&gt;) to take the transpose of &lt;code&gt;arr_2&lt;/code&gt;. Since &lt;code&gt;arr_1&lt;/code&gt; is 1x3 and &lt;code&gt;transpose(arr_2)&lt;/code&gt; is 3x1, this results in the scalar, or dot, product.&lt;/p&gt;
&lt;p&gt;With NumPy arrays, operations like multiplication with the asterisk (&lt;code&gt;*&lt;/code&gt;) operate element-wise by default:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [1]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&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;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[4]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;np.array([ 4, 10, 18])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are first importing the NumPy package and assigning it to the name &lt;code&gt;np&lt;/code&gt;. Then you are creating two one-dimensional arrays. Notice the syntax for creating arrays in NumPy. It starts with &lt;code&gt;np.array()&lt;/code&gt;, which should be read as &amp;ldquo;from within &lt;code&gt;np&lt;/code&gt;, find &lt;code&gt;array()&lt;/code&gt;.&amp;rdquo; Then, you have to pass a Python list or tuple to the array constructor that contains the elements of the array. In this case, you are passing a Python list, denoted by the square brackets.&lt;/p&gt;
&lt;p&gt;Finally, on input line 4, you are multiplying &lt;code&gt;arr_1&lt;/code&gt; and &lt;code&gt;arr_2&lt;/code&gt;. Notice that the result on output line 4 is another array with the elements 4, 10, and 18, the same result as the element-wise multiplication in MATLAB.&lt;/p&gt;
&lt;p&gt;If you want to perform the dot or scalar product for two arrays in NumPy, you have two options. The preferred option is to use the matrix multiplication operator (&lt;code&gt;@&lt;/code&gt;) added in Python 3.5. You may see some older code also use &lt;code&gt;dot()&lt;/code&gt; from the NumPy library and pass the two arrays:&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;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[5]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;32&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[6]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;32&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, input line 5 uses the matrix multiplication operator to find the scalar product of &lt;code&gt;arr_1&lt;/code&gt; and &lt;code&gt;arr_2&lt;/code&gt;. As expected, the result is 32. Input line 5 uses &lt;code&gt;dot()&lt;/code&gt; and should be read as &amp;ldquo;from within &lt;code&gt;np&lt;/code&gt;, find &lt;code&gt;dot()&lt;/code&gt; and pass &lt;code&gt;arr_1&lt;/code&gt; and &lt;code&gt;arr_2&lt;/code&gt;.&amp;rdquo; You can see that the result is identical.&lt;/p&gt;
&lt;p&gt;Notice that NumPy did not require you to transpose &lt;code&gt;arr_2&lt;/code&gt; before performing the scalar product. You&amp;rsquo;ll learn more about this feature in the next section.&lt;/p&gt;
&lt;h3 id=&quot;one-dimensional-arrays-are-vectors-in-numpy&quot;&gt;One-Dimensional Arrays Are Vectors in NumPy&lt;/h3&gt;
&lt;p&gt;As you saw in the last section, MATLAB insists that the dimensions of arrays align when performing matrix multiplication, while NumPy is a little bit more flexible. This is because of how one-dimensional arrays are treated in MATLAB versus in NumPy.&lt;/p&gt;
&lt;p&gt;In MATLAB, every array always has at least two dimensions, even if only implicitly. You can see this by checking the &lt;code&gt;size()&lt;/code&gt; of a single number:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;size&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;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     1     1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you are finding the size of the integer 1. You can see that the result is an array with 1 row and 1 column.&lt;/p&gt;
&lt;p&gt;You can create row vectors or column vectors in MATLAB, and switch between them with the transpose operator (&lt;code&gt;&#39;&lt;/code&gt;) or &lt;code&gt;transpose()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&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;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  3×1 logical array&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;   1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   1&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  1×3 logical array&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;   1   1   1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating two vectors: &lt;code&gt;arr_1&lt;/code&gt; and &lt;code&gt;arr_2&lt;/code&gt;. Arrays with values in one dimension only are called vectors. &lt;code&gt;arr_1&lt;/code&gt; is a row vector because the elements are arranged in one row and three columns, whereas &lt;code&gt;arr_2&lt;/code&gt; is a column vector because the elements are arranged in three rows and one column. In MATLAB, elements are put into different columns by separating them with a comma in the assignment and elements are put into different rows by separating them with a semicolon.&lt;/p&gt;
&lt;p&gt;Then, you are checking the equality of the transpose of &lt;code&gt;arr_1&lt;/code&gt; with &lt;code&gt;arr_2&lt;/code&gt;, and you find that all of the elements are equal and the result is a column vector of logical values. Finally, you are checking the equality of the transpose of &lt;code&gt;arr_2&lt;/code&gt; with &lt;code&gt;arr_1&lt;/code&gt;, and you find that all of the elements are equal and the result is a row vector of logical values.&lt;/p&gt;
&lt;p&gt;You can see that in MATLAB, even vectors have two dimensions associated with them: &lt;strong&gt;rows&lt;/strong&gt; and &lt;strong&gt;columns&lt;/strong&gt;. When the transpose is performed, the rows are switched with the columns, and the shape of the array is changed. This means there are two types of vectors in MATLAB: &lt;strong&gt;row-vectors&lt;/strong&gt; and &lt;strong&gt;column-vectors&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In NumPy, there are three types of one-dimensional arrays or vectors. The default is an N-element vector with only one dimension. This is different from the default in MATLAB, where every array has at least 2 dimensions. This one-dimensional vector in NumPy does not have a sense of rows and columns, since for a one-dimensional structure, it does not matter in general whether the elements are stored in rows or in columns, only how many elements there are.&lt;/p&gt;
&lt;p&gt;You can see an example of creating this kind of array in the following example. In the next few examples, there are extra spaces added before and after parentheses to clarify the syntax. These spaces are usually not considered good Python style, but they&amp;rsquo;re in the example to help you see what&amp;rsquo;s going on:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [1]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_vec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(3,)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating a default 3-element vector in NumPy. On input line 1, you import NumPy and make it available under &lt;code&gt;np&lt;/code&gt;. On input line 2 you are creating the array and storing it in &lt;code&gt;arr_vec&lt;/code&gt;. You are passing the list &lt;code&gt;[1, 2, 3]&lt;/code&gt; to &lt;code&gt;array()&lt;/code&gt;, where the list has 3 elements and none of the elements are themselves lists. This creates the 3-element array with only one dimension.&lt;/p&gt;
&lt;p&gt;You can verify that this is the case by displaying the shape of the array, as shown on input line 3. That line should be read as &amp;ldquo;from within &lt;code&gt;arr_vec&lt;/code&gt; (an array), find the &lt;code&gt;shape&lt;/code&gt;.&amp;rdquo; The &lt;code&gt;shape&lt;/code&gt; of the array is equivalent to &lt;code&gt;size()&lt;/code&gt; in MATLAB. In this case, the shape is &lt;code&gt;(3,)&lt;/code&gt;, indicating there are three elements and only one dimension, since there is not a second number after the comma.&lt;/p&gt;
&lt;p&gt;You can also create row-vectors and column-vectors in NumPy, analogous to the row-vectors and column-vectors in MATLAB. NumPy&amp;rsquo;s &lt;code&gt;array()&lt;/code&gt; takes a flat list or a nested list as input. Using the flat list gets you a one-dimensional, N-element vector. By using the nested list, you can create arrays of any dimension that you want. A nested list means that there are one or more lists contained within an outer list. Here&amp;rsquo;s an example of a nested list:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you see an outer list that has 2 elements. Each of these 2 elements of the outer list is another, nested, list that has three elements, the integers 1-3 and 4-6. In terms of arrays, you can think of the number of elements of each inner list as the number of columns, and the number of nested lists is the number of rows. This is easier to see if you change the formatting:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&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;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code is still valid Python syntax, but it emphasizes how the inner lists are each a row of the array, and the number of elements in each inner list is the number of columns. In this case, we would have an array with 2 rows and 3 columns. We can use these nested lists to create row-vectors and column-vectors in NumPy arrays:&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;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[5]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(1, 3)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating a row array or vector by using a nested list. Input line 4 is passing &lt;code&gt;[[1, 2, 3]]&lt;/code&gt; to &lt;code&gt;array()&lt;/code&gt;. You can break out the formatting of this nested list to see how it looks:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, there is one row in this nested list with three columns. On input line 5, you are displaying the shape of this array. As expected, the shape is &lt;code&gt;(1, 3)&lt;/code&gt;, or one row with three columns.&lt;/p&gt;
&lt;p&gt;Finally, you can create a column array by including three nested lists in the input:&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;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;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;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;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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [7]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[7]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(3, 1)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, input line 6 is passing &lt;code&gt;[[1], [2], [3]]&lt;/code&gt; to the array constructor. You can break out the formatting of this nested list to see how it looks:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, there are three rows in this nested list with one column each. On input line 7, you are displaying the shape of this array. As expected, the shape is &lt;code&gt;(3, 1)&lt;/code&gt;, or three rows with one column.&lt;/p&gt;
&lt;p&gt;Since the general N-element vector has no sense of rows and columns, NumPy is able to shape the vector in whatever way makes sense for the operation being performed. You saw this in the last section, where the NumPy array did not need to be transposed to perform the scalar product, whereas the MATLAB array did need to be transposed.&lt;/p&gt;
&lt;p&gt;Trying to take the transpose of the N-element vector does not change the shape of the array. You can take the transpose using either &lt;code&gt;np.transpose()&lt;/code&gt; or the &lt;code&gt;.T&lt;/code&gt; attribute of the array:&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;In [8]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_vec_transp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [9]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_vec_transp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[9]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(3,)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are taking the transpose of the N-element vector &lt;code&gt;arr_vec&lt;/code&gt; and printing its shape. Notice that the shape is the same as the shape of the original &lt;code&gt;arr_vec&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, if you are using row-vectors and column-vectors, you will need to ensure that the dimensions are appropriate for the particular operation. For instance, trying to take the scalar product of the row vector with itself will result in an error:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [10]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  File &amp;quot;&amp;lt;ipython-input-10-2b447c0bc8d5&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    arr_row @ arr_row&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;with gufunc signature (n?,k),(k,m?)-&amp;gt;(n?,m?) (size 1 is different from 3)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, trying to find the scalar product of the row vector with itself results in a &lt;code&gt;ValueError&lt;/code&gt; informing you that the dimensions of the arrays are not aligned. Using &lt;code&gt;dot()&lt;/code&gt; gives the same error but a slightly different message:&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;In [11]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  File &amp;quot;&amp;lt;ipython-input-11-d6e191b317ae&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    np.dot(arr_row, arr_row)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are using &lt;code&gt;dot()&lt;/code&gt; from the &lt;code&gt;np&lt;/code&gt; namespace to attempt to find the scalar product of two 1x3 row-vectors. Since this operation is not permitted, NumPy raises a &lt;code&gt;ValueError&lt;/code&gt;, similar to the matrix multiplication operator.&lt;/p&gt;
&lt;p&gt;Instead, you need to take the transpose of one of the 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;In [12]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[12]:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;array([[1],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [2],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [3]])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [13]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sc_prod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [14]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sc_prod&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[14]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([[14]])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On input line 12, you are taking the transpose of the row vector to turn it into a column vector using the transpose attribute (&lt;code&gt;.T&lt;/code&gt;). This is shown in corresponding output line, where the elements are arranged to form a column for printing purposes. Then, you are taking the scalar product of the vector with its transpose, producing an array with a single value, 14. Notice that this is a 1x1 array, so to access just the value, you need to access the first element in each dimension:&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;In [15]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sc_prod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[15]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(1, 1)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [16]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sc_prod&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;gh&quot;&gt;Out[16]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;14&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are verifying that the shape is 1x1, and then accessing the first element in each dimension located at the 0th index. Remember that Python uses 0 as the first index, not 1.&lt;/p&gt;
&lt;p&gt;You can use the nested lists to create arrays of any shape that you want. To create a three-by-three array (two-dimensional), simply include three elements in each of your three nested lists:&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;In [17]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&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;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;8&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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [18]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[18]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(3, 3)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have nested three lists with three elements each into the constructor. As shown by the shape, this produces a 3x3 array with the elements 1 through 9.&lt;/p&gt;
&lt;h3 id=&quot;creating-arrays-is-very-flexible-in-numpy&quot;&gt;Creating Arrays Is Very Flexible in NumPy&lt;/h3&gt;
&lt;p&gt;MATLAB and NumPy both allow you to explicitly specify the specific elements in an array, as you have seen in the previous section. In addition to this direct creation of arrays, both MATLAB and NumPy support a number of other methods to create arrays without explicitly specifying each element. The NumPy project maintains a detailed list of the &lt;a href=&quot;https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html#table-of-rough-matlab-numpy-equivalents&quot;&gt;equivalent functions between MATLAB and NumPy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many functions operate identically between MATLAB and NumPy. This includes commonly used functions like &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html&quot;&gt;&lt;code&gt;linspace()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/generated/numpy.logspace.html&quot;&gt;&lt;code&gt;logspace()&lt;/code&gt;&lt;/a&gt; to generate evenly spaced data and &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/generated/numpy.ones.html&quot;&gt;&lt;code&gt;ones()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html#numpy.zeros&quot;&gt;&lt;code&gt;zeros()&lt;/code&gt;&lt;/a&gt; to generate arrays of a given shape filled with ones and zeros, respectively. The full list of ways to create arrays in NumPy is listed &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/routines.array-creation.html&quot;&gt;in the official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The one big difference between MATLAB and NumPy in terms of array creation routines is that MATLAB supports simply using the colon to create an array, while NumPy does not. Instead, NumPy uses &lt;a href=&quot;https://realpython.com/how-to-use-numpy-arange/&quot;&gt;&lt;code&gt;arange()&lt;/code&gt;&lt;/a&gt; to create an array between specified values.&lt;/p&gt;
&lt;p&gt;In MATLAB, you can use a &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/colon.html&quot;&gt;colon&lt;/a&gt; to create an array specification range. In general, you can use up to 2 colons in a specification. The syntax is as follows:&lt;/p&gt;
&lt;div class=&quot;highlight matlab&quot;&gt;&lt;pre&gt;&lt;span&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;stop&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;step&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this syntax, the, first method only uses one colon and specifies the start and stop values. The second method includes a second colon, where the value before the first colon is the start, the middle value is the step, and the last value is the stop.&lt;/p&gt;
&lt;p&gt;Try out these examples to experiment with this syntax:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;6&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;arr_1 =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     1     2     3     4     5     6&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     1     6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you are using the single colon with the start and stop to generate an array with the values from 1 to 6. You can see that when the step is omitted, it defaults to a value of 1. Notice that MATLAB includes both the start and the stop values in the array, and that the size of the array is 6 elements long. Next, change the value of the step size to create a new array:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;arr_2 =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     1     3     5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you are using the two colons syntax with the start, step, and stop. The start value is 1, the step is 2, and the stop value is 6, so MATLAB starts with 1, increments to 3, and then to 5. The next step would exceed the stop value, so MATLAB does not include the stop value in the array. Next, change the starting value to create another new array:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;arr_3 =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     2     4     6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you are again using the two colon method, but you are specifying the start value as 2 instead of 1. In this case, MATLAB starts at 2, increments to 4, increments to 6, and then has reached the stop value so does not go further. Notice that in this case, the the stop value of 6 is included in the array.&lt;/p&gt;
&lt;p&gt;With NumPy, you can use &lt;code&gt;arange()&lt;/code&gt; to create an array with specific start, stop, and step values. However, &lt;code&gt;arange()&lt;/code&gt; has one big difference from MATLAB, which is that the stop value is &lt;em&gt;not&lt;/em&gt; included in the resulting array. The reason for this is so that the size of the array is equal to &lt;code&gt;stop - start&lt;/code&gt; for the default case of a step size of 1. Notice in MATLAB that the size of the array of the integers from 1 to 6 is 6, but 6 - 1 = 5.&lt;/p&gt;
&lt;p&gt;There are three ways to use &lt;code&gt;arange()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you only pass one argument to &lt;code&gt;arange()&lt;/code&gt;, it will be interpreted as the stop value. The start value defaults to 0 and the step defaults to 1. If you pass two arguments to &lt;code&gt;arange()&lt;/code&gt;, they are interpreted as the start and stop values. Finally, you can pass all three of start, stop, and step to &lt;code&gt;arange()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Notice that the order of the arguments is different from MATLAB, going &lt;code&gt;start&lt;/code&gt;, &lt;code&gt;stop&lt;/code&gt;, &lt;code&gt;step&lt;/code&gt; in Python. If you&amp;rsquo;re having trouble remembering the order that these arguments go, remember that you can &lt;a href=&quot;#functions-accept-positional-and-keyword-arguments-in-python&quot;&gt;use keyword arguments in Python&lt;/a&gt; to be explicit about what each argument means.&lt;/p&gt;
&lt;p&gt;You can try out &lt;code&gt;arange()&lt;/code&gt; with the following examples:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&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;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([1, 2, 3, 4, 5, 6])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[4]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(6,)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you are creating an array that contains the values from 1 to 6. As in MATLAB, if the step is omitted, it defaults to 1. Notice that you had to pass the stop value 7 so that the array stopped at 6. However, the size of the resulting array is 7 - 1 = 6 elements long. Next, you should see how to change the step size:&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;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&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;7&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;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[6]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([1, 3, 5])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating an array that contains the values from 1 to 6, incrementing by two between each element. The step is two, so NumPy starts with 1, increments to 3, and then to 5. The next step would equal the stop value, but NumPy does not include the stop value in the array. Notice that the formula to compute the size of the array is a little bit different, since the step size is not 1.&lt;/p&gt;
&lt;p&gt;With step sizes other than 1, the size of the array can be computed by &lt;code&gt;(stop - start)/step&lt;/code&gt; if this results in an integer value. In this case, the size of the array is (7 - 1)/2 = 3 elements, as expected. If &lt;code&gt;(stop - start)/step&lt;/code&gt; results in a floating point number, the size of the array is equal to the next largest integer as demonstrated in the next 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;In [7]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [8]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_3&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[8]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([2, 4, 6])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you are creating an array that contains the values from 2 to 6, incrementing by two between each element. The step is two, so NumPy starts with 2, increments to 4, and then to 6. The next step would exceed the stop value, so NumPy stops at 6. Notice that the size of the array is (7 - 2)/2 = 2.5, so the next highest integer is 3 elements, as expected.&lt;/p&gt;
&lt;p&gt;Finally, you should usually use integer arguments to &lt;code&gt;arange()&lt;/code&gt; in NumPy and the colon operator in MATLAB. If you use floating point values (numbers with decimals), especially for the step, the elements may not come out exactly as you expect. If you want to use floating point numbers, &lt;code&gt;linspace()&lt;/code&gt; is a better choice in general.&lt;/p&gt;
&lt;h3 id=&quot;the-colon-operator-is-very-powerful-in-numpy&quot;&gt;The Colon Operator Is Very Powerful in NumPy&lt;/h3&gt;
&lt;p&gt;In MATLAB, the colon operator is used to perform a number of useful tasks. As you saw, it can be used to create arrays, and it can also be used to index or slice arrays. When indexing arrays, MATLAB supports the &lt;code&gt;end&lt;/code&gt; keyword to extend the specified range to the end of that dimension, as you &lt;a href=&quot;#the-last-element-of-a-sequence-has-index-1-in-python&quot;&gt;saw earlier&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     3     5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are indexing &lt;code&gt;arr_1&lt;/code&gt; starting at the second index and going to the end of the array. You can also specify a specific index as the stop value:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     2     3     4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating an array &lt;code&gt;arr_2&lt;/code&gt; with the numbers 1 through 6, inclusive. Then, you are specifying the second element as the start value and the fourth element as the stop value in the slice. MATLAB supports the two-colon increment syntax when indexing as well:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     2     4     6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are indexing the array, starting at the second element, skipping every other element, until the end of the array. You can also use &lt;code&gt;end&lt;/code&gt; as the starting point of the slice with a negative step:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     6     5     4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are indexing &lt;code&gt;arr_2&lt;/code&gt; starting from the last value, decrementing by 1, and ending at the 4th element. Finally, you can slice all of the element in a dimension by using just a bare colon:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(:)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     1     2     3     4     5     6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are selecting all of the first dimension of the array using just the colon.&lt;/p&gt;
&lt;p&gt;NumPy and Python in general also use the colon for the slice syntax, but the order of the values is slightly different. In Python, the order is &lt;code&gt;start : stop : step&lt;/code&gt;, whereas in MATLAB, it is &lt;code&gt;start : step : stop&lt;/code&gt;, as you saw earlier. In addition, in NumPy you can omit start or stop and they will have default a value of 0 (or the first element) for start and the last element for stop. In MATLAB, you must specify start &lt;em&gt;and&lt;/em&gt; stop if you want to specify either of them. Thus, Python does not have the &lt;code&gt;end&lt;/code&gt; keyword, since you can omit &lt;code&gt;stop&lt;/code&gt; to achieve the same behavior.&lt;/p&gt;
&lt;p&gt;Try out the following examples of the slice syntax in NumPy:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([3, 5])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating an array with the integers from 1 to 6, inclusive, skipping every other number. Then, you are slicing the array taking the second element (index 1) until the end of the array. Notice that the stop value was omitted, so it defaulted to the last element in the array.&lt;/p&gt;
&lt;p&gt;You can also specify a specific element as the stop value. You saw in using &lt;code&gt;arange()&lt;/code&gt; that the array did not include the stop value. The same is true of the slice syntax in Python, the slice will include everything up to, but not including, the stop index:&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;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&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;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[5]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([2, 3, 4])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating an array with the integers from 1 to 6, inclusive. Then, you are slicing the array starting at the second element (index 1, value 2) until the fourth element (index 3, value 4). However, you specified the stop index as 4 (the fifth element in the array, value 5). The reason Python includes up to the (stop - 1) index is the same reason &lt;code&gt;arange()&lt;/code&gt; does not include the stop value, so that the length of the resulting array is equal to &lt;code&gt;stop - start&lt;/code&gt;. Next, try changing the step of the slice:&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;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[6]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([2, 4, 6])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are slicing the array starting at the second element (index 1), going until the end of the array, and taking every second element. This results in an array with the values 2, 4, and 6. Notice that the stop value was omitted in the slice syntax, so it defaulted to the last element in the array.&lt;/p&gt;
&lt;p&gt;You can also use a negative step in the slicing syntax for Python:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [7]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;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;gh&quot;&gt;Out[7]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([6, 5, 4])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are not specifying the start index of the slice, you are specifying the stop value should be index 2, and the step should be -1. Since the start index is not specified and the step is negative, the start value is assumed to be the last element in the array (or the first element in the reversed array). For the stop value, index 2 has the value of 3 and one index before that (in the reversed array) is index 3 with the value of 4.&lt;/p&gt;
&lt;p&gt;Finally, just like in MATLAB, a bare colon means to select all of the elements from that dimension:&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;In [8]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:]&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[8]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;array([1, 2, 3, 4, 5, 6])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;array-slices-are-views-of-arrays-in-numpy&quot;&gt;Array Slices Are Views of Arrays in NumPy&lt;/h3&gt;
&lt;p&gt;In MATLAB, when you access a slice of an array and assign it to a variable, MATLAB will make a copy of that portion of the array into your new variable. This means that when you assign values to the slice, the original array is not affected. Try out this example to help explain the differences of MATLAB vs Python:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&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;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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_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;k&quot;&gt;end&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;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;arr_2 =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     5     6&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;     8     9&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;arr_2 =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    10     6&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;     8     9&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;arr_1 =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     1     2     3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;     4     5     6&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;     7     8     9&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you have created a 3x3 array &lt;code&gt;arr_1&lt;/code&gt; storing the values from 1 through 9. Then, you create a 2x2 slice of the original array storing from the second value to the end in both dimensions, &lt;code&gt;arr_2&lt;/code&gt;. On the third input line, you assign the value 10 to the upper left element in &lt;code&gt;arr_2&lt;/code&gt;. Finally, you print &lt;code&gt;arr_1&lt;/code&gt; again to verify that none of the values in &lt;code&gt;arr_1&lt;/code&gt; have changed.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical detail&lt;/strong&gt;: MATLAB employs a &lt;strong&gt;copy-on-write&lt;/strong&gt; memory management system, where an array may only be copied to a new memory location when it is modified. You can read more about MATLAB memory management in &lt;a href=&quot;https://blogs.mathworks.com/loren/2006/05/10/memory-management-for-functions-and-variables/&quot;&gt;Memory Management for Functions and Variables&lt;/a&gt; on the Mathworks blog and in &lt;a href=&quot;https://undocumentedmatlab.com/blog/internal-matlab-memory-optimizations&quot;&gt;Internal Matlab memory optimizations&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In NumPy, slices of arrays are views to the original array. This behavior saves memory and time, since the values in the array don&amp;rsquo;t have to be copied to a new location. However, it means that changes that you make to a slice from an array will change the original array. You should try the following code to see how this works:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&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;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;8&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;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr_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;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[4]:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;array([[5, 6],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [8, 9]])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating a 3x3 array &lt;code&gt;arr_1&lt;/code&gt; storing the values from 1 through 9. Then, you create a 2x2 slice of the original array storing from the second value to the end in both dimensions, &lt;code&gt;arr_2&lt;/code&gt;. Notice that the Python indexing is 0-based, so the second element has the index 1. Finally, you are printing &lt;code&gt;arr_2&lt;/code&gt; to verify that it is a 2x2 array.&lt;/p&gt;
&lt;p&gt;Now you should see what happens when you change a value in &lt;code&gt;arr_2&lt;/code&gt;. Like in the MATLAB example, you should change the upper left element of &lt;code&gt;arr_2&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;In [5]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [6]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[6]:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;array([[10,  6],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [ 8,  9]])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [7]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[7]:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;array([[ 1,  2,  3],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [ 4, 10,  6],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [ 7,  8,  9]])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you first assign the upper left element in &lt;code&gt;arr_2&lt;/code&gt;, at index (0, 0) to have a value of 10. Then you print &lt;code&gt;arr_2&lt;/code&gt; to verify that the appropriate value has changed. Finally, you print &lt;code&gt;arr_1&lt;/code&gt; and see that the value in the middle of the array has changed from 5 to 10!&lt;/p&gt;
&lt;p&gt;This is what is meant by &lt;code&gt;arr_2&lt;/code&gt; being a &lt;strong&gt;view&lt;/strong&gt; of &lt;code&gt;arr_1&lt;/code&gt;. Since it is a view, &lt;code&gt;arr_2&lt;/code&gt; points to the same memory location as &lt;code&gt;arr_1&lt;/code&gt;, so updating &lt;code&gt;arr_2&lt;/code&gt; also updates &lt;code&gt;arr_1&lt;/code&gt; because the value stored in the memory location accessed by both &lt;code&gt;arr_2&lt;/code&gt; and &lt;code&gt;arr_1&lt;/code&gt; has been updated. This also goes the other direction, where changing values in &lt;code&gt;arr_1&lt;/code&gt; will update the value in &lt;code&gt;arr_2&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;In [8]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;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;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;42&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [9]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[9]:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;array([[ 1,  2,  3],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [ 4, 10,  6],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [ 7,  8, 42]])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [10]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[10]:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;array([[10,  6],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [ 8, 42]])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are assigning the bottom right element of &lt;code&gt;arr_1&lt;/code&gt; to have the value 42. Remember that in Python, an index of &lt;code&gt;-1&lt;/code&gt; means the last value on that dimension. Then you are printing &lt;code&gt;arr_1&lt;/code&gt; to verify that the lower right value has changed from 9 to 42. Finally, you are printing &lt;code&gt;arr_2&lt;/code&gt;, and you see for &lt;code&gt;arr_2&lt;/code&gt; as well, the bottom right value has changed from 9 to 42.&lt;/p&gt;
&lt;p&gt;If you want to generate a copy of an array, you can use &lt;code&gt;np.copy()&lt;/code&gt;. Copying an array creates a new place in memory for the copy to be stored, so changes to the copied array do not affect the original:&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;In [11]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [12]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;37&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [13]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_3&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[13]:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;array([[10,  6],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [37, 42]])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [14]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[14]:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;array([[10,  6],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [ 8, 42]])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating &lt;code&gt;arr_3&lt;/code&gt; as a copy of &lt;code&gt;arr_2&lt;/code&gt;. Then, you are changing the element in the second row, first column to have the value of 37. Then, you are printing &lt;code&gt;arr_3&lt;/code&gt; to verify that the specified change has been made. Finally, you are printing &lt;code&gt;arr_2&lt;/code&gt; to verify that no changes have occurred in &lt;code&gt;arr_2&lt;/code&gt;, as expected.&lt;/p&gt;
&lt;h2 id=&quot;tips-and-tricks-to-make-your-code-pythonic&quot;&gt;Tips and Tricks to Make Your Code Pythonic&lt;/h2&gt;
&lt;p&gt;Like any other programming language, Python code written by experienced Python developers often has a particular look and feel to it. This is because they are able to take advantage of specific idioms in Python to work with Python rather than against Python. Developers coming from other languages often miss out on what makes code Pythonic in their first projects.&lt;/p&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll learn some tips and tricks to make your code Pythonic and level up your Python skills. There are many more tips and tricks than you can learn here, so feel free to check out &lt;a href=&quot;https://realpython.com/learning-paths/writing-pythonic-code/&quot;&gt;Write More Pythonic Code&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;you-should-not-use-semicolons-to-end-lines-in-python&quot;&gt;You Should Not Use Semicolons to End Lines in Python&lt;/h3&gt;
&lt;p&gt;In MATLAB, ending a line of code with a semicolon &lt;code&gt;;&lt;/code&gt; suppresses the output from that line. For instance, assigning a variable will print the value of the variable after the assignment if the semicolon is omitted.&lt;/p&gt;
&lt;p&gt;In Python, you should not end lines of code with semicolons. It is unnecessary, since Python does not change its behavior whether the line is ended with a semicolon or not. So you can save yourself a key stroke and not bother including the semicolon in your scripts and libraries.&lt;/p&gt;
&lt;p&gt;There is one case in Python where the semicolon is useful. When you want to execute several statements, but you cannot include a newline character in the input, you can separate the statements with semicolons. This is mostly useful to execute very short scripts from the command prompt or terminal. For instance, to find the particular Python executable that is running, you can type 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;gp&quot;&gt;$&lt;/span&gt; python -c &lt;span class=&quot;s2&quot;&gt;&amp;quot;import sys; print(sys.executable)&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/home/eleanor/anaconda3/bin/python&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are executing the Python interpreter in the &lt;code&gt;python&lt;/code&gt; executable and passing the &lt;code&gt;-c&lt;/code&gt; switch. This switch takes the next argument and executes it within the interpreter. Since the shell environment would execute if you pressed &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; to insert a new line, you can type the whole script on one line.&lt;/p&gt;
&lt;p&gt;In this case, you have two logical statements that need to be separated by the semicolon. First you are importing the built-in &lt;code&gt;sys&lt;/code&gt; library and then you are printing the value of &lt;code&gt;sys.executable&lt;/code&gt;. In this example, the Python interpreter that the shell is running comes from the &lt;code&gt;/home/eleanor/anaconda3/bin/python&lt;/code&gt; file.&lt;/p&gt;
&lt;h3 id=&quot;you-should-not-import-from-a-module-in-python&quot;&gt;You Should Not Import &lt;code&gt;*&lt;/code&gt; From a Module in Python&lt;/h3&gt;
&lt;p&gt;In a &lt;a href=&quot;#namespaces-are-one-honking-great-idea-in-python&quot;&gt;previous section&lt;/a&gt;, you read about how namespaces are one honking great idea in Python. In MATLAB, all functions are part of the global namespace by default, so every function and class name has to be unique. Python solves this problem by using namespaces and requiring you to specify which module a function should come from.&lt;/p&gt;
&lt;p&gt;You will find tutorials around the Web that suggest you write 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;a_module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are using the &lt;code&gt;*&lt;/code&gt; to indicate that Python should import everything that is contained in &lt;code&gt;a_module&lt;/code&gt; and put it in the current scope without a prefix. This is slightly more convenient, because you no longer have to prefix functions and classes from &lt;code&gt;a_module&lt;/code&gt; with anything, you can just use them directly. However, it is not a good practice because you don&amp;rsquo;t know what names are defined in &lt;code&gt;a_module&lt;/code&gt; and whether or not they will override any existing names in your current scope.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical Note:&lt;/strong&gt; When you &lt;code&gt;from a_module import *&lt;/code&gt;, Python imports all of the names listed in a special variable called &lt;code&gt;__all__&lt;/code&gt; in &lt;code&gt;a_module&lt;/code&gt;. However, if that variable is not defined, Python will import all of the variables, functions, and classes defined in &lt;code&gt;a_module&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;you-should-take-advantage-of-the-different-data-types-in-python&quot;&gt;You Should Take Advantage of the Different Data Types in Python&lt;/h3&gt;
&lt;p&gt;MATLAB, with its heritage as a linear algebra and array focused language, treats most data types as arrays of some sort. This often makes it a little bit tricky to work with more advanced data types like &lt;code&gt;structs&lt;/code&gt;, &lt;code&gt;containers.Map&lt;/code&gt;, cell arrays, and more.&lt;/p&gt;
&lt;p&gt;Python has several built-in data types that are very flexible and can be used to accomplish a number of useful tasks. The major ones that you&amp;rsquo;ll learn about in this section are &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;lists&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-dicts/&quot;&gt;dictionaries&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;lists&quot;&gt;Lists&lt;/h4&gt;
&lt;p&gt;Python lists are mutable sequences of values. Lists can contain heterogeneous data, which means that each element of the list can be of a different type. Because lists are mutable, you can change the value of any element in the list, or add or remove values from the list, without creating a new list object.&lt;/p&gt;
&lt;p&gt;Since lists are sequences, you can create loops that iterate over them. In Python, you do not need to access each element of a list with an index in a &lt;a href=&quot;https://realpython.com/courses/python-for-loop/&quot;&gt;&lt;code&gt;for&lt;/code&gt; loop&lt;/a&gt;, as you would do in MATLAB:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_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;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; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i&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;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    disp(arr_1(i))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating an array &lt;code&gt;arr_1&lt;/code&gt; with the integers from 1 to 6, taking every other number. Then you are creating a &lt;code&gt;for&lt;/code&gt; loop where the loop variable goes from 1 to the length of &lt;code&gt;arr_1&lt;/code&gt;. Finally, you are displaying the value of the element of &lt;code&gt;arr_1&lt;/code&gt; at the loop variable on each step by using the loop variable &lt;code&gt;i&lt;/code&gt; to index &lt;code&gt;arr_1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Python, you should not use an index for the list when you loop over it. Instead, you should loop directly over the items in a list:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lst_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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;b&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lst_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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;   ...:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, on input line 1 you are first creating a Python list with three elements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The integer &lt;code&gt;1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The string &lt;code&gt;&quot;b&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The float &lt;code&gt;3.0&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This list is assigned to &lt;code&gt;lst_1&lt;/code&gt;. Then you are using a &lt;code&gt;for&lt;/code&gt; loop to access each item in the list in turn. On each iteration, the next value in the list is put into the variable &lt;code&gt;item&lt;/code&gt; that you specified on the &lt;code&gt;for&lt;/code&gt; line. Then, you are printing the value of &lt;code&gt;item&lt;/code&gt; on each iteration.&lt;/p&gt;
&lt;p&gt;Notice in the previous example that you could loop over the value of each element in the list without using an index. Nonetheless, sometimes you want to access the index of each item in the list as you&amp;rsquo;re looping over it. For those cases, Python provides &lt;code&gt;enumerate()&lt;/code&gt; that returns the index and the value of the item:&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;In [3]: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lst_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;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;The index is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{index}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; and the item is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{item}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;   ...:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The index is 0 and the item is 1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The index is 1 and the item is b&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The index is 2 and the item is 3.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are looping over &lt;code&gt;lst_1&lt;/code&gt; again, but this time, you are using &lt;code&gt;enumerate()&lt;/code&gt; to get both the index and the item. Then you are printing the value of the index and item on each loop iteration. As you can see from the result, the index values start at 0 as expected, but you do not need to use the index to access the item from the list.&lt;/p&gt;
&lt;p&gt;In summary, you should not write Python code 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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lst_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;lst_1&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating a range of integers from 0 to the length of &lt;code&gt;lst_1&lt;/code&gt; and then you are accessing each element in the list by its index. This can lead to &lt;a href=&quot;https://en.wikipedia.org/wiki/Off-by-one_error&quot;&gt;off-by-one&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Off-by-one_error#Fencepost_error&quot;&gt;fencepost&lt;/a&gt; errors. Instead, you should write code that loops over the list 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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lst_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;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can read a lot more about lists in &lt;a href=&quot;https://realpython.com/python-lists-tuples&quot;&gt;Lists and Tuples in Python&lt;/a&gt; and about &lt;code&gt;for&lt;/code&gt; loops and iteration in &lt;a href=&quot;https://realpython.com/python-for-loop&quot;&gt;Python &amp;ldquo;for&amp;rdquo; Loops (Definite Iteration)&lt;/a&gt;. There is also a more advanced concept called &lt;strong&gt;list comprehensions&lt;/strong&gt; that you can learn about in &lt;a href=&quot;https://realpython.com/courses/using-list-comprehensions-effectively&quot;&gt;Using List Comprehensions Effectively&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;dictionaries&quot;&gt;Dictionaries&lt;/h4&gt;
&lt;p&gt;In MATLAB, you can create a map data type with &lt;code&gt;containers.Map()&lt;/code&gt;. This kind of data structure is useful when you have two pieces of data that are always related to each other and you want to connect them together. For instance, you can map cities to their population with a &lt;code&gt;containers.Map()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &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;n&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Cleveland&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Pittsburgh&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Hartford&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;                           [383793,301048,122587]);&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &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;s&quot;&gt;&amp;#39;Cleveland&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;ans =&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;     383793&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are creating a &lt;code&gt;containers.Map()&lt;/code&gt; on the first line. The first argument is a cell array of character arrays with the city names. These are called the &lt;strong&gt;keys&lt;/strong&gt; of the map. The second argument is an array of populations. These are called the &lt;strong&gt;values&lt;/strong&gt; of the map. Then, you are accessing the value of the population in Cleveland by indexing the map with a character array.&lt;/p&gt;
&lt;p&gt;You can assign new values into the map by assigning to an undefined key value:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &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;s&quot;&gt;&amp;#39;Providence&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;180393&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you try to access a key that does not exist, you will receive an error message:&lt;/p&gt;
&lt;div class=&quot;highlight matlab 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; &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;s&quot;&gt;&amp;#39;New York City&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Error using containers.Map/subsref&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The specified key is not present in this container.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python has an equivalent data structure called a &lt;strong&gt;dictionary&lt;/strong&gt;. To create a Python &lt;a href=&quot;https://realpython.com/python-dicts/&quot;&gt;dictionary&lt;/a&gt;, you can use curly braces and specify the keys and values with each other:&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;In [1]: &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;gp&quot;&gt;   ...: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Cleveland&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;383_793&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;   ...: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Pittsburgh&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;301_048&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;   ...: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hartford&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;122_587&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &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;s2&quot;&gt;&amp;quot;Cleveland&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;383793&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, on input line 1 you are creating the dictionary of cities using curly braces. Notice that the key and value are specified together, separated by a colon. The values are specified with &lt;code&gt;_&lt;/code&gt; in the numbers, a feature available since Python 3.6. This does not change the value of the number, it only makes it easier to read very large numbers. Then, you are accessing the value at the &lt;code&gt;&quot;Cleveland&quot;&lt;/code&gt; key using square brackets, similar to the indexing syntax for lists and arrays.&lt;/p&gt;
&lt;p&gt;You can add new keys to the dictionary by assigning to them:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;In [3]: &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;s2&quot;&gt;&amp;quot;Providence&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;180_393&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you assigned a new key &lt;code&gt;&quot;Providence&quot;&lt;/code&gt; to the dictionary with a value of 180,393. If you try to access a key that is not in the dictionary, you will get a &lt;code&gt;KeyError&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;In [4]: &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;s2&quot;&gt;&amp;quot;New York City&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  File &amp;quot;&amp;lt;ipython-input-4-6ebe5b35f3ea&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    cities[&amp;quot;New York City&amp;quot;]&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;KeyError: &amp;#39;New York City&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you are trying to access the dictionary using the &lt;code&gt;&quot;New York City&quot;&lt;/code&gt; key. However, this key does not exist in the dictionary so Python raises a &lt;code&gt;KeyError&lt;/code&gt; letting you know that &lt;code&gt;&quot;New York City&quot;&lt;/code&gt; is not an option.&lt;/p&gt;
&lt;p&gt;You can read a lot more about Python dictionaries in &lt;a href=&quot;https://realpython.com/python-dicts&quot;&gt;Dictionaries in Python&lt;/a&gt; and &lt;code&gt;KeyError&lt;/code&gt; exceptions in &lt;a href=&quot;https://realpython.com/python-keyerror&quot;&gt;Python KeyError Exceptions and How to Handle Them&lt;/a&gt;. You can also iterate through dictionaries and use dictionary comprehensions, similar to list comprehensions. You can read about these topics in &lt;a href=&quot;https://realpython.com/iterate-through-dictionary-python&quot;&gt;How to Iterate Through a Dictionary in Python&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;exceptions-help-you-control-program-flow-in-python&quot;&gt;Exceptions Help You Control Program Flow in Python&lt;/h3&gt;
&lt;p&gt;MATLAB and Python both use errors and exceptions to let you know when something has gone wrong in the code. In this section, you will learn about common exceptions in Python and how you can handle them appropriately.&lt;/p&gt;
&lt;p&gt;If you want an introduction to Python exceptions overall, you can read &lt;a href=&quot;https://realpython.com/python-exceptions/&quot;&gt;Python Exceptions: An Introduction&lt;/a&gt;. When a Python exception is raised, it produces a &lt;strong&gt;traceback&lt;/strong&gt;. You can read about how to interpret the traceback in &lt;a href=&quot;https://realpython.com/python-traceback/&quot;&gt;Understanding Python Tracebacks&lt;/a&gt;. Understanding tracebacks is very helpful to interpret and correct Python exceptions in general. There are a few specific cases that usually have the same resolution. You&amp;rsquo;ll see those described in the rest of this section.&lt;/p&gt;
&lt;h4 id=&quot;nameerror&quot;&gt;NameError&lt;/h4&gt;
&lt;p&gt;Python &lt;code&gt;NameError&lt;/code&gt; exceptions are usually the result of a variable being undefined. When you see a &lt;code&gt;NameError&lt;/code&gt;, check your code for typos and misspelled variable names. You can use the debugging features and the variable explorer in Spyder to find out which variables are defined.&lt;/p&gt;
&lt;h4 id=&quot;syntaxerror&quot;&gt;SyntaxError&lt;/h4&gt;
&lt;p&gt;Python &lt;code&gt;SyntaxError&lt;/code&gt; exceptions mean that you have input some improper syntax. This is usually caused by mismatched brackets, when you have only the opening bracket or closing bracket but not the matching one. These exceptions usually point to the line &lt;em&gt;after&lt;/em&gt; the place where the problem is located.&lt;/p&gt;
&lt;p&gt;Another common &lt;code&gt;SyntaxError&lt;/code&gt; is using only one equals sign in an &lt;code&gt;if&lt;/code&gt; statement. In this case, you either meant not-equals (&lt;code&gt;!=&lt;/code&gt;) or equals (&lt;code&gt;==&lt;/code&gt;), so you can correct the line.&lt;/p&gt;
&lt;h4 id=&quot;keyerror&quot;&gt;KeyError&lt;/h4&gt;
&lt;p&gt;Python &lt;code&gt;KeyError&lt;/code&gt; exceptions occur when you try to access a key in a dictionary that does not exist. You can use &lt;a href=&quot;https://realpython.com/python-dicts/#dgetltkeygt-ltdefaultgt&quot;&gt;&lt;code&gt;.get()&lt;/code&gt;&lt;/a&gt; to retrieve a key from a dictionary if it exists, or return a default value if the key does not exist. You can read more about &lt;code&gt;KeyError&lt;/code&gt; exceptions in &lt;a href=&quot;https://realpython.com/python-keyerror/&quot;&gt;Python KeyError Exceptions and How to Handle Them&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;indexerror&quot;&gt;IndexError&lt;/h4&gt;
&lt;p&gt;Python &lt;code&gt;IndexError&lt;/code&gt; exceptions occur when you are trying to access the index of an array or list that does not exist. This usually means the array or list you are trying to access has fewer elements than the index you are trying to access. You can use the debugging features and the variable explorer in Spyder to see the size of lists and arrays and make sure you&amp;rsquo;re only accessing indices that exist.&lt;/p&gt;
&lt;h4 id=&quot;importerrormodulenotfounderror&quot;&gt;ImportError/ModuleNotFoundError&lt;/h4&gt;
&lt;p&gt;Python &lt;code&gt;ImportError&lt;/code&gt; and &lt;code&gt;ModuleNotFoundError&lt;/code&gt; exceptions occur when you try to import a module that Python cannot find. This might be because it is installed in a different &lt;code&gt;conda&lt;/code&gt; environment or &lt;code&gt;virtualenv&lt;/code&gt;, or it might be because you forgot to install the package.&lt;/p&gt;
&lt;p&gt;The solution to this error is usually to &lt;code&gt;conda install&lt;/code&gt; or &lt;code&gt;pip install&lt;/code&gt; the package and make sure the correct environment is activated. If you&amp;rsquo;re not using the &lt;code&gt;base&lt;/code&gt; environment in &lt;code&gt;conda&lt;/code&gt;, you also need to make sure to install Spyder or Jupyter into your environment.&lt;/p&gt;
&lt;h4 id=&quot;typeerrorvalueerror&quot;&gt;TypeError/ValueError&lt;/h4&gt;
&lt;p&gt;Python &lt;code&gt;TypeError&lt;/code&gt; exceptions happen when an argument is of the wrong type. This happens most commonly when you pass an argument of the wrong type into a function. For instance, a function that works with numbers would raise a &lt;code&gt;TypeError&lt;/code&gt; if a string were passed in.&lt;/p&gt;
&lt;p&gt;A related exception is the &lt;code&gt;ValueError&lt;/code&gt;. This exception happens when an argument is of the correct type, but has an incorrect value. For instance, a function that works only with positive numbers would raise a &lt;code&gt;ValueError&lt;/code&gt; if a negative number were passed in.&lt;/p&gt;
&lt;h4 id=&quot;attributeerror&quot;&gt;AttributeError&lt;/h4&gt;
&lt;p&gt;Python &lt;code&gt;AttributeError&lt;/code&gt; exceptions happen when you try to access an attribute of an object when the object does not have that attribute. You will often see this error associated with the message &lt;code&gt;NoneType object has no attribute&lt;/code&gt;. This message most likely means that a function has returned &lt;code&gt;None&lt;/code&gt; instead of the object you were expecting and you are trying to access an attribute that would be present on the real object, but is not defined for &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;how-to-handle-exceptions-in-python&quot;&gt;How to Handle Exceptions in Python&lt;/h3&gt;
&lt;p&gt;MATLAB allows you to &lt;code&gt;try&lt;/code&gt; a statement of code and &lt;code&gt;catch&lt;/code&gt; any errors that are thrown by the code. Once you have caught an error, you can do further processing of the error and assign variables based on the type of error. The &lt;a href=&quot;https://www.mathworks.com/help/matlab/ref/try.html&quot;&gt;MATLAB documentation&lt;/a&gt; has several good examples of how this would look in MATLAB.&lt;/p&gt;
&lt;p&gt;In Python, one big difference from MATLAB is that you can choose to catch only certain types of exceptions and handle them. This allows all other exceptions to continue to be displayed to the user. If you want to learn more about how to do this in Python, you can read &lt;a href=&quot;https://realpython.com/python-exceptions/#the-try-and-except-block-handling-exceptions&quot;&gt;The &lt;code&gt;try&lt;/code&gt; and &lt;code&gt;except&lt;/code&gt; Block: Handling Exceptions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To see how this works, you can try 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;In [1]: &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;In [2]: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_sqrt&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;gp&quot;&gt;   ...: &lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;You passed the argument: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{number!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;gp&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;gp&quot;&gt;   ...: &lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;return&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;n&quot;&gt;number&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;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;   ...: &lt;/span&gt;       &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;You passed a number that cannot be operated on&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;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;   ...: &lt;/span&gt;       &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;You passed an argument that was not a number&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;   ...:&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [3]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;You passed the argument: 4.0&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[3]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;2.0&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_sqrt&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;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;You passed the argument: -1.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;You passed a number that cannot be operated on&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [4]: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;4.0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;You passed the argument: &amp;#39;4.0&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;You passed an argument that was not a number&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, on input line 1 you are importing the built-in &lt;code&gt;math&lt;/code&gt; library. Then, starting on input line 2, you are defining a function called &lt;code&gt;my_sqrt()&lt;/code&gt; that will take one argument, called &lt;code&gt;number&lt;/code&gt;. Inside the function definition, you first print the argument that the user passed.&lt;/p&gt;
&lt;p&gt;Next, you enter the &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;except&lt;/code&gt; block. First, you try to take the square root of the input argument and return the result. If taking the square root of the argument results in an error, Python will catch that error and check which type of error was raised.&lt;/p&gt;
&lt;p&gt;You have defined code that handles two specific exceptions: &lt;code&gt;ValueError&lt;/code&gt; and &lt;code&gt;TypeError&lt;/code&gt;. If &lt;code&gt;math.sqrt()&lt;/code&gt; raises a &lt;code&gt;ValueError&lt;/code&gt;, your code will print a message that the number cannot be operated on. If &lt;code&gt;math.sqrt()&lt;/code&gt; raises a &lt;code&gt;TypeError&lt;/code&gt;, your code will print a message that the argument was not a number. If any other type of exception is raised by &lt;code&gt;math.sqrt()&lt;/code&gt;, that error will be passed through without any processing, since there is no handler for any other error types.&lt;/p&gt;
&lt;p&gt;More specifically, Python checks for any error that is raised by the code in the &lt;code&gt;try&lt;/code&gt; block. In your case, you only defined one line of code in the &lt;code&gt;try&lt;/code&gt; block, but this is not required, and you can have as many lines as you want there. However, it is usually a good practice to minimize the number of lines of code in the &lt;code&gt;try&lt;/code&gt; block so you can be very specific about which code is raising any errors.&lt;/p&gt;
&lt;p&gt;On input line 3, you are testing out &lt;code&gt;my_sqrt()&lt;/code&gt;. First, you pass the value 4.0 to the function. The function prints the argument, and &lt;code&gt;math.sqrt()&lt;/code&gt; has no problems taking the square root of 4, resulting in 2.0 on the output line.&lt;/p&gt;
&lt;p&gt;On input line 4, you are passing -1.0 as the argument to &lt;code&gt;my_sqrt()&lt;/code&gt;. As you may recall, taking the square root of negative numbers results in a complex number, which the &lt;code&gt;math.sqrt()&lt;/code&gt; function is not equipped to handle. Taking the square root of a negative number using &lt;code&gt;math.sqrt()&lt;/code&gt; raises a &lt;code&gt;ValueError&lt;/code&gt;. You exception handler catches this &lt;code&gt;ValueError&lt;/code&gt; and prints the message that the number cannot be operated on.&lt;/p&gt;
&lt;p&gt;On input line 5, you are passing &lt;code&gt;&quot;4.0&quot;&lt;/code&gt; as the argument to &lt;code&gt;my_sqrt()&lt;/code&gt;. In this case, &lt;code&gt;math.sqrt()&lt;/code&gt; does not know how to take the square root of a string, even though that string appears to represent a number. You can see that you have passed a string by the quotes in the statement giving the value of the argument: &lt;code&gt;You passed the argument: &#39;4.0&#39;&lt;/code&gt;. Since &lt;code&gt;math.sqrt()&lt;/code&gt; cannot take the square root of a string, it raises a &lt;code&gt;TypeError&lt;/code&gt;, and your function prints the message that the argument was not a number.&lt;/p&gt;
&lt;h3 id=&quot;there-is-an-official-guide-to-writing-good-code-in-python&quot;&gt;There Is an Official Guide to Writing Good Code in Python&lt;/h3&gt;
&lt;p&gt;The Python community has developed a set of recommendations for how to style your Python code. These are codified in a document called PEP 8, which stands for Python Enhancement Proposal #8. PEP 8 can be found in full on the &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot;&gt;Python website&lt;/a&gt;. You can also learn more about good Python style in &lt;a href=&quot;https://realpython.com/python-pep8/&quot;&gt;How to Write Beautiful Python Code With PEP 8&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/courses/idiomatic-python-101&quot;&gt;Idiomatic Python 101&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Perhaps the most important principle in PEP 8 is the saying that &amp;ldquo;a foolish consistency is the hobgoblin of little minds.&amp;rdquo; This means that you should follow the recommendations in PEP 8 for almost all of your code, but there may be some limited cases where it is a good idea not to follow the PEP 8 recommendations. For instance, if you are working with an existing codebase that has its own style, you should follow that style where it diverges from PEP 8. You can see an excellent discussion of this principle from Raymond Hettinger, one of the core Python developers, in a &lt;a href=&quot;https://realpython.com/must-watch-pycon-talks/#2-beyond-pep-8-best-practices-for-beautiful-intelligible-code&quot;&gt;talk from PyCon 2015&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Aside from reading PEP 8, you can use a few Python packages to automatically make sure that your code fits the style guidelines. &lt;a href=&quot;https://flake8.readthedocs.io&quot;&gt;Flake8&lt;/a&gt; is a code linter that reads your code and makes suggestions for how you can improve it. This is similar to the feature in the MATLAB code editor that makes improvement suggestions. In addition, packages such as &lt;a href=&quot;https://black.readthedocs.io/en/stable/&quot;&gt;Black&lt;/a&gt;, &lt;a href=&quot;https://github.com/google/yapf&quot;&gt;yapf&lt;/a&gt;, and &lt;a href=&quot;https://github.com/hhatto/autopep8&quot;&gt;autopep8&lt;/a&gt; will automatically format your code to be compliant with PEP 8 or your own style rules. Using these packages can help your code feel more Pythonic and help you learn good Python style!&lt;/p&gt;
&lt;h2 id=&quot;python-has-a-fantastic-and-supportive-community&quot;&gt;Python Has a Fantastic and Supportive Community&lt;/h2&gt;
&lt;p&gt;Python is known for having a very supportive, open, and welcoming community. Whether you are a brand new developer or an experienced one, whether you&amp;rsquo;re brand new to Python or have been to a dozen conferences, the community is there to support you and what you want to do.&lt;/p&gt;
&lt;p&gt;The community starts with the Python Package Index (called PyPI or the CheeseShop, a reference to the Monty Python sketch), which houses hundreds of thousands of different Python packages that you can download for free. These packages can be installed using &lt;code&gt;pip&lt;/code&gt;, a package manager that comes bundled with Python. This means that adding the functionality you need to Python can be as simple as &lt;code&gt;pip install package&lt;/code&gt; or if you&amp;rsquo;re using Anaconda, &lt;code&gt;conda install package&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since Python is used in so many different areas of software development, data science, science, and engineering, there are always people around who want to talk about Python. Most large cities around the world have Python meetup groups. You can go to these groups to learn about Python by hearing people speak about their work or work on some open-source code.&lt;/p&gt;
&lt;p&gt;A few times a year, these groups coalesce into different PyCons which happen on every continent around the globe. PyCon North America is the largest of these, with several thousand attendees every year. You can read all about what it&amp;rsquo;s like to attend in &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;p&gt;Python also has a very strong online community. If you have a question about programming in Python, you can ask on &lt;a href=&quot;https://stackoverflow.com/questions/tagged/python&quot;&gt;StackOverflow&lt;/a&gt; and some of the world-leading Python experts will be able to help you out. Make sure to follow the instructions for &lt;a href=&quot;https://stackoverflow.com/help/how-to-ask&quot;&gt;how to ask a question&lt;/a&gt; on StackOverflow. Remember that the more effort you put into your question, the more likely you are to either find the answer yourself (&lt;em&gt;hooray!&lt;/em&gt;) or get a good answer from someone else.&lt;/p&gt;
&lt;p&gt;If you want to follow along with Python&amp;rsquo;s development, you can sign up for one of the &lt;a href=&quot;https://www.python.org/community/lists/&quot;&gt;mailing lists&lt;/a&gt; covering different aspects of Python&amp;rsquo;s community. The general mailing list for asking questions about writing programs in Python is called &lt;a href=&quot;https://mail.python.org/mailman/listinfo/python-list&quot;&gt;comp.lang.python&lt;/a&gt;. If you are interested in the development of Python itself, you can follow the &lt;a href=&quot;https://mail.python.org/mailman3/lists/python-dev.python.org/&quot;&gt;python-dev&lt;/a&gt; mailing list.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in learning much, much more about Python development, you can check out the &lt;em&gt;Real Python&lt;/em&gt; &lt;a href=&quot;https://realpython.com/learning-paths/&quot;&gt;Learning Paths&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&quot;areas-where-you-should-still-use-matlab&quot;&gt;Areas Where You Should Still Use MATLAB®&lt;/h2&gt;
&lt;p&gt;In spite of the awesome community and terrific packages, there are still one or two areas where MATLAB works better than Python. The main place where Python can&amp;rsquo;t compete with MATLAB is the Simulink Toolbox. This toolbox offers advanced capabilities for signal processing and modeling in a convenient graphical interface.&lt;/p&gt;
&lt;p&gt;Python does not have an equivalent graphical interface to these kinds of functions. However, to the extent that Simulink is a convenient interface to ordinary differential equation solvers, Python has equivalent solvers as in MATLAB and the underlying functionality of Simulink can certainly be replicated in Python.&lt;/p&gt;
&lt;p&gt;Otherwise, you can do anything in Python that you can do in MATLAB! If you can think of work that you can do with MATLAB, but you&amp;rsquo;re not sure how to do it in Python, let us know in the comments and we&amp;rsquo;ll be able to help with suggestions.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations, you now have the knowledge you need to switch your MATLAB code to Python! In this article, you learned a little bit about what Python is, how to set up your computer to use Python, and how to convert your code from MATLAB to Python.&lt;/p&gt;
&lt;p&gt;Python is a really huge language and community, with lots to learn and lots of people to learn from. Remember, you weren&amp;rsquo;t a MATLAB expert the first time you opened the MATLAB development environment, and the same is true about the first time you write some Python code. Come back to this article as often as you need to improve your skills and learn more about becoming a Python wizard!&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;There are tons of resources on the Web covering the differences in MATLAB vs Python. Here are a few of the resources that I found helpful when I transitioned from MATLAB to Python:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=YkCegjtoHFQ&quot;&gt;Webinar: Python for MATLAB Users, What You Need to Know (Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.enthought.com/white-paper-matlab-to-python&quot;&gt;MATLAB To Python Whitepaper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tobydriscoll.net/blog/matlab-vs.-julia-vs.-python/&quot;&gt;Matlab vs. Julia vs. Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://phillipmfeldman.org/Python/Advantages_of_Python_Over_Matlab.html&quot;&gt;Eight Advantages of Python Over MATLAB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.stat.washington.edu/~hoytak/blog/whypython.html&quot;&gt;10 Reasons Python Rocks for Research (And a Few Reasons it Doesn&amp;rsquo;t)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Python args and kwargs: Demystified</title>
      <id>https://realpython.com/python-kwargs-and-args/</id>
      <link href="https://realpython.com/python-kwargs-and-args/"/>
      <updated>2019-09-04T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how to use args and kwargs in Python to add more flexibility to your functions. You&#39;ll also take a closer look at the single and double-asterisk unpacking operators, which you can use to unpack any iterable object in Python.</summary>
      <content type="html">
        &lt;p&gt;Sometimes, when you look at a function definition in Python, you might see that it takes two strange arguments: &lt;strong&gt;&lt;code&gt;*args&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;**kwargs&lt;/code&gt;&lt;/strong&gt;. If you&amp;rsquo;ve ever wondered what these peculiar variables are, or why your IDE defines them in &lt;code&gt;main()&lt;/code&gt;, then this article is for you. You&amp;rsquo;ll learn how to use args and kwargs in Python to add more flexibility to your functions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of the article, you&amp;rsquo;ll know:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; actually mean&lt;/li&gt;
&lt;li&gt;How to use &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; in function definitions&lt;/li&gt;
&lt;li&gt;How to use a single asterisk (&lt;code&gt;*&lt;/code&gt;) to unpack iterables&lt;/li&gt;
&lt;li&gt;How to use two asterisks (&lt;code&gt;**&lt;/code&gt;) to unpack dictionaries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article assumes that you already know how to define Python functions and work with &lt;a href=&quot;https://realpython.com/lessons/mutable-data-structures-lists-dictionaries/&quot;&gt;lists and dictionaries&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-cheat-sheet-shortened&quot; data-focus=&quot;false&quot;&gt;Click here to get a Python Cheat Sheet&lt;/a&gt; and learn the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;passing-multiple-arguments-to-a-function&quot;&gt;Passing Multiple Arguments to a Function&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;*args&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;**kwargs&lt;/code&gt;&lt;/strong&gt; allow you to pass multiple arguments or keyword arguments to a function. Consider the following example. This is a simple function that takes two arguments and returns their sum:&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;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This function works fine, but it&amp;rsquo;s limited to only two arguments. What if you need to sum a varying number of arguments, where the specific number of arguments passed is only determined at runtime? Wouldn&amp;rsquo;t it be great to create a function that could sum &lt;em&gt;all&lt;/em&gt; the integers passed to it, no matter how many there are?&lt;/p&gt;
&lt;h2 id=&quot;using-the-python-args-variable-in-function-definitions&quot;&gt;Using the Python args Variable in Function Definitions&lt;/h2&gt;
&lt;p&gt;There are a few ways you can pass a varying number of arguments to a function. The first way is often the most intuitive for people that have experience with collections. You simply pass a list or a &lt;a href=&quot;https://realpython.com/python-sets/&quot;&gt;set&lt;/a&gt; of all the arguments to your function. So for &lt;code&gt;my_sum()&lt;/code&gt;, you could pass a list of all the integers you need to add:&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;# sum_integers_list.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_integers&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;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;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_integers&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;x&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;span class=&quot;n&quot;&gt;list_of_integers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_of_integers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This implementation works, but whenever you call this function you&amp;rsquo;ll also need to create a list of arguments to pass to it. This can be inconvenient, especially if you don&amp;rsquo;t know up front all the values that should go into the list.&lt;/p&gt;
&lt;p&gt;This is where &lt;code&gt;*args&lt;/code&gt; can be really useful, because it allows you to pass a varying number of positional arguments. Take 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;# sum_integers_args.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&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;c1&quot;&gt;# Iterating over the Python args tuple&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&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;x&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;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you&amp;rsquo;re no longer passing a list to &lt;code&gt;my_sum()&lt;/code&gt;. Instead, you&amp;rsquo;re passing three different positional arguments. &lt;code&gt;my_sum()&lt;/code&gt; takes all the parameters that are provided in the input and packs them all into a single iterable object named &lt;code&gt;args&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that &lt;strong&gt;&lt;code&gt;args&lt;/code&gt; is just a name.&lt;/strong&gt; You&amp;rsquo;re not required to use the name &lt;code&gt;args&lt;/code&gt;. You can choose any name that you prefer, such as &lt;code&gt;integers&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;# sum_integers_args_2.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_sum&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;integers&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;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;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;integers&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;x&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;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The function still works, even if you pass the iterable object as &lt;code&gt;integers&lt;/code&gt; instead of &lt;code&gt;args&lt;/code&gt;. All that matters here is that you use the &lt;strong&gt;unpacking operator&lt;/strong&gt; (&lt;code&gt;*&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Bear in mind that the iterable object you&amp;rsquo;ll get using the unpacking operator &lt;code&gt;*&lt;/code&gt; is &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;not a &lt;code&gt;list&lt;/code&gt; but a &lt;code&gt;tuple&lt;/code&gt;&lt;/a&gt;. A &lt;code&gt;tuple&lt;/code&gt; is similar to a &lt;code&gt;list&lt;/code&gt; in that they both support slicing and iteration. However, tuples are very different in at least one aspect: lists are &lt;a href=&quot;https://realpython.com/courses/immutability-python/&quot;&gt;mutable&lt;/a&gt;, while tuples are not. To test this, run the following code. This script tries to change a value of a list:&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;# change_list.py&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The value located at the very first index of the list should be updated to &lt;code&gt;9&lt;/code&gt;. If you execute this script, you will see that the list indeed gets modified:&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 change_list.py
&lt;span class=&quot;go&quot;&gt;[9, 2, 3]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first value is no longer &lt;code&gt;0&lt;/code&gt;, but the updated value &lt;code&gt;9&lt;/code&gt;. Now, try to do the same with a tuple:&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;# change_tuple.py&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_tuple&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you see the same values, except they&amp;rsquo;re held together as a tuple. If you try to execute this script, you will see that the Python interpreter returns an &lt;a href=&quot;https://realpython.com/python-exceptions/&quot;&gt;error&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 change_tuple.py
&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;change_tuple.py&amp;quot;, line 3, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    my_tuple[0] = 9&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;TypeError: &amp;#39;tuple&amp;#39; object does not support item assignment&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is because a tuple is an immutable object, and its values cannot be changed after assignment. Keep this in mind when you&amp;rsquo;re working with tuples and &lt;code&gt;*args&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;using-the-python-kwargs-variable-in-function-definitions&quot;&gt;Using the Python kwargs Variable in Function Definitions&lt;/h2&gt;
&lt;p&gt;Okay, now you&amp;rsquo;ve understood what &lt;code&gt;*args&lt;/code&gt; is for, but what about &lt;code&gt;**kwargs&lt;/code&gt;? &lt;code&gt;**kwargs&lt;/code&gt; works just like &lt;code&gt;*args&lt;/code&gt;, but instead of accepting positional arguments it accepts keyword (or &lt;strong&gt;named&lt;/strong&gt;) arguments. Take 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;# concatenate.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;concatenate&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;result&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;c1&quot;&gt;# Iterating over the Python kwargs dictionary&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&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;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;concatenate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Real&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Is&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Great&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;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;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you execute the script above, &lt;code&gt;concatenate()&lt;/code&gt; will iterate through the Python kwargs &lt;a href=&quot;https://realpython.com/python-dicts/&quot;&gt;dictionary&lt;/a&gt; and concatenate all the values it finds:&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 concatenate.py
&lt;span class=&quot;go&quot;&gt;RealPythonIsGreat!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Like &lt;code&gt;args&lt;/code&gt;, &lt;code&gt;kwargs&lt;/code&gt; is just a name that can be changed to whatever you want. Again, what is important here is the use of the &lt;strong&gt;unpacking operator&lt;/strong&gt; (&lt;code&gt;**&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;So, the previous example could be written like this:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# concatenate_2.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;concatenate&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;words&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;s2&quot;&gt;&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;arg&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&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;arg&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;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;concatenate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Real&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Is&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Great&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that in the example above the iterable object is a standard &lt;code&gt;dict&lt;/code&gt;. If you &lt;a href=&quot;https://realpython.com/iterate-through-dictionary-python/&quot;&gt;iterate over the dictionary&lt;/a&gt; and want to return its values, like in the example shown, then you must use &lt;code&gt;.values()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In fact, if you forget to use this method, you will find yourself iterating through the &lt;strong&gt;keys&lt;/strong&gt; of your Python kwargs dictionary instead, like in 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;# concatenate_keys.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;concatenate&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;result&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;c1&quot;&gt;# Iterating over the keys of the Python kwargs dictionary&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&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;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&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;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;concatenate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Real&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Is&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Great&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, if you try to execute this example, you&amp;rsquo;ll notice the following output:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python concatenate_keys.py
&lt;span class=&quot;go&quot;&gt;abcde&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, if you don&amp;rsquo;t specify &lt;code&gt;.values()&lt;/code&gt;, your function will iterate over the keys of your Python kwargs dictionary, returning the wrong result.&lt;/p&gt;
&lt;h2 id=&quot;ordering-arguments-in-a-function&quot;&gt;Ordering Arguments in a Function&lt;/h2&gt;
&lt;p&gt;Now that you have learned what &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; are for, you are ready to start writing functions that take a varying number of input arguments. But what if you want to create a function that takes a changeable number of both positional &lt;em&gt;and&lt;/em&gt; named arguments?&lt;/p&gt;
&lt;p&gt;In this case, you have to bear in mind that &lt;strong&gt;order counts&lt;/strong&gt;. Just as non-default arguments have to precede default arguments, so &lt;code&gt;*args&lt;/code&gt; must come before &lt;code&gt;**kwargs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To recap, the correct order for your parameters is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Standard arguments&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*args&lt;/code&gt; arguments&lt;/li&gt;
&lt;li&gt;&lt;code&gt;**kwargs&lt;/code&gt; arguments&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example, this function definition is correct:&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;# correct_function_definition.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;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;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;*args&lt;/code&gt; variable is appropriately listed before &lt;code&gt;**kwargs&lt;/code&gt;. But what if you try to modify the order of the arguments? For example, consider the following 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;# wrong_function_definition.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;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;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;k&quot;&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, &lt;code&gt;**kwargs&lt;/code&gt; comes before &lt;code&gt;*args&lt;/code&gt; in the function definition. If you try to run this example, you&amp;rsquo;ll receive an error from the interpreter:&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 wrong_function_definition.py
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;wrong_function_definition.py&amp;quot;, line 2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    def my_function(a, b, **kwargs, *args):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;                                    ^&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;SyntaxError: invalid syntax&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, since &lt;code&gt;*args&lt;/code&gt; comes after &lt;code&gt;**kwargs&lt;/code&gt;, the Python interpreter throws a &lt;code&gt;SyntaxError&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;unpacking-with-the-asterisk-operators&quot;&gt;Unpacking With the Asterisk Operators: &lt;code&gt;*&lt;/code&gt; &amp;amp; &lt;code&gt;**&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;You are now able to use &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; to define Python functions that take a varying number of input arguments. Let&amp;rsquo;s go a little deeper to understand something more about the &lt;strong&gt;unpacking operators&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The single and double asterisk unpacking operators were introduced in Python 2. As of the 3.5 release, they have become even more powerful, thanks to &lt;a href=&quot;https://www.python.org/dev/peps/pep-0448/&quot;&gt;PEP 448&lt;/a&gt;. In short, the unpacking operators are operators that unpack the values from iterable objects in Python. The single asterisk operator &lt;code&gt;*&lt;/code&gt; can be used on any iterable that Python provides, while the double asterisk operator &lt;code&gt;**&lt;/code&gt; can only be used on dictionaries.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with 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;c1&quot;&gt;# print_list.py&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code defines a list and then prints it to the standard output:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python print_list.py
&lt;span class=&quot;go&quot;&gt;[1, 2, 3]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note how the list is printed, along with the corresponding brackets and commas.&lt;/p&gt;
&lt;p&gt;Now, try to prepend the unpacking operator &lt;code&gt;*&lt;/code&gt; to the name of your list:&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;# print_unpacked_list.py&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&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;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, the &lt;code&gt;*&lt;/code&gt; operator tells &lt;code&gt;print()&lt;/code&gt; to unpack the list first.&lt;/p&gt;
&lt;p&gt;In this case, the output is no longer the list itself, but rather &lt;em&gt;the content&lt;/em&gt; of the list:&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 print_unpacked_list.py
&lt;span class=&quot;go&quot;&gt;1 2 3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Can you see the difference between this execution and the one from &lt;code&gt;print_list.py&lt;/code&gt;? Instead of a list, &lt;code&gt;print()&lt;/code&gt; has taken three separate arguments as the input.&lt;/p&gt;
&lt;p&gt;Another thing you&amp;rsquo;ll notice is that in &lt;code&gt;print_unpacked_list.py&lt;/code&gt;, you used the unpacking operator &lt;code&gt;*&lt;/code&gt; to call a function, instead of in a function definition. In this case, &lt;code&gt;print()&lt;/code&gt; takes all the items of a list as though they were single arguments.&lt;/p&gt;
&lt;p&gt;You can also use this method to call your own functions, but if your function requires a specific number of arguments, then the iterable you unpack must have the same number of arguments.&lt;/p&gt;
&lt;p&gt;To test this behavior, consider this script:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# unpacking_call.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&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;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_sum&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;my_list&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;my_sum()&lt;/code&gt; explicitly states that &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt; are required arguments.&lt;/p&gt;
&lt;p&gt;If you run this script, you&amp;rsquo;ll get the sum of the three numbers in &lt;code&gt;my_list&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 unpacking_call.py
&lt;span class=&quot;go&quot;&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The 3 elements in &lt;code&gt;my_list&lt;/code&gt; match up perfectly with the required arguments in &lt;code&gt;my_sum()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now look at the following script, where &lt;code&gt;my_list&lt;/code&gt; has 4 arguments instead of 3:&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;# wrong_unpacking_call.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&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;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_sum&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;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, &lt;code&gt;my_sum()&lt;/code&gt; still expects just three arguments, but the &lt;code&gt;*&lt;/code&gt; operator gets 4 items from the list. If you try to execute this script, you&amp;rsquo;ll see that the Python interpreter is unable to run it:&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 wrong_unpacking_call.py
&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;wrong_unpacking_call.py&amp;quot;, line 6, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    my_sum(*my_list)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;TypeError: my_sum() takes 3 positional arguments but 4 were given&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you use the &lt;code&gt;*&lt;/code&gt; operator to unpack a list and pass arguments to a function, it&amp;rsquo;s exactly as though you&amp;rsquo;re passing every single argument alone. This means that you can use multiple unpacking operators to get values from several lists and pass them all to a single function.&lt;/p&gt;
&lt;p&gt;To test this 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;# sum_integers_args_3.py&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&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;x&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;span class=&quot;n&quot;&gt;list1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list2&lt;/span&gt; &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;4&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;list3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&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;9&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;my_sum&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;list1&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;list2&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;list3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you run this example, all three lists are unpacked. Each individual item is passed to &lt;code&gt;my_sum()&lt;/code&gt;, resulting in the following output:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python sum_integers_args_3.py
&lt;span class=&quot;go&quot;&gt;45&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are other convenient uses of the unpacking operator. For example, say you need to split a list into three different parts. The output should show the first value, the last value, and all the values in between. With the unpacking operator, you can do this in just one line of code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# extract_list_body.py&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;a&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;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_list&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;a&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;b&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;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, &lt;code&gt;my_list&lt;/code&gt; contains 6 items. The first variable is assigned to &lt;code&gt;a&lt;/code&gt;, the last to &lt;code&gt;c&lt;/code&gt;, and all other values are packed into a new list &lt;code&gt;b&lt;/code&gt;. If you run the &lt;a href=&quot;https://realpython.com/run-python-scripts/&quot;&gt;script&lt;/a&gt;, &lt;code&gt;print()&lt;/code&gt; will show you that your three variables have the values you would expect:&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 extract_list_body.py
&lt;span class=&quot;go&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[2, 3, 4, 5]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Another interesting thing you can do with the unpacking operator &lt;code&gt;*&lt;/code&gt; is to split the items of any iterable object. This could be very useful if you need to merge two lists, for instance:&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;# merging_lists.py&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_first_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_second_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_merged_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_first_list&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;my_second_list&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;my_merged_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The unpacking operator &lt;code&gt;*&lt;/code&gt; is prepended to both &lt;code&gt;my_first_list&lt;/code&gt; and &lt;code&gt;my_second_list&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you run this script, you&amp;rsquo;ll see that the result is a merged list:&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 merging_lists.py
&lt;span class=&quot;go&quot;&gt;[1, 2, 3, 4, 5, 6]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can even merge two different dictionaries by using the unpacking operator &lt;code&gt;**&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;# merging_dicts.py&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_first_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;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;B&amp;quot;&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;my_second_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;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;mi&quot;&gt;3&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;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_merged_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_first_dict&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;my_second_dict&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;my_merged_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, the iterables to merge are &lt;code&gt;my_first_dict&lt;/code&gt; and &lt;code&gt;my_second_dict&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Executing this code outputs a merged dictionary:&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 merging_dicts.py
&lt;span class=&quot;go&quot;&gt;{&amp;#39;A&amp;#39;: 1, &amp;#39;B&amp;#39;: 2, &amp;#39;C&amp;#39;: 3, &amp;#39;D&amp;#39;: 4}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Remember that the &lt;code&gt;*&lt;/code&gt; operator works on &lt;em&gt;any&lt;/em&gt; iterable object. It can also be used to unpack a &lt;a href=&quot;https://realpython.com/python-strings/&quot;&gt;string&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;c1&quot;&gt;# string_to_list.py&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &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;s2&quot;&gt;&amp;quot;RealPython&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Python, strings are iterable objects, so &lt;code&gt;*&lt;/code&gt; will unpack it and place all individual values in a list &lt;code&gt;a&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 string_to_list.py
&lt;span class=&quot;go&quot;&gt;[&amp;#39;R&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;l&amp;#39;, &amp;#39;P&amp;#39;, &amp;#39;y&amp;#39;, &amp;#39;t&amp;#39;, &amp;#39;h&amp;#39;, &amp;#39;o&amp;#39;, &amp;#39;n&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The previous example seems great, but when you work with these operators it&amp;rsquo;s important to keep in mind the seventh rule of &lt;a href=&quot;https://www.python.org/dev/peps/pep-0020/&quot;&gt;&lt;em&gt;The Zen of Python&lt;/em&gt;&lt;/a&gt; by Tim Peters: &lt;em&gt;Readability counts&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;To see why, 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;# mysterious_statement.py&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;RealPython&amp;quot;&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;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There&amp;rsquo;s the unpacking operator &lt;code&gt;*&lt;/code&gt;, followed by a variable, a comma, and an assignment. That&amp;rsquo;s a lot packed into one line! In fact, this code is no different from the previous example. It just takes the string &lt;code&gt;RealPython&lt;/code&gt; and assigns all the items to the new list &lt;code&gt;a&lt;/code&gt;, thanks to the unpacking operator &lt;code&gt;*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The comma after the &lt;code&gt;a&lt;/code&gt; does the trick. When you use the unpacking operator with variable assignment, Python requires that your resulting variable is either a list or a tuple. With the trailing comma, you have actually defined a tuple with just one named variable &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;While this is a neat trick, many Pythonistas would not consider this code to be very readable. As such, it&amp;rsquo;s best to use these kinds of constructions sparingly.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You are now able to use &lt;strong&gt;&lt;code&gt;*args&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;**kwargs&lt;/code&gt;&lt;/strong&gt; to accept a changeable number of arguments in your functions. You have also learned something more about the unpacking operators. &lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; actually mean&lt;/li&gt;
&lt;li&gt;How to use &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; in function definitions&lt;/li&gt;
&lt;li&gt;How to use a single asterisk (&lt;code&gt;*&lt;/code&gt;) to unpack iterables&lt;/li&gt;
&lt;li&gt;How to use two asterisks (&lt;code&gt;**&lt;/code&gt;) to unpack dictionaries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you still have questions, don&amp;rsquo;t hesitate to reach out in the comments section below! To learn more about the use of the asterisks in Python, have a look at &lt;a href=&quot;https://treyhunner.com/2018/10/asterisks-in-python-what-they-are-and-how-to-use-them/&quot;&gt;Trey Hunner&amp;rsquo;s article on the subject&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>Lists and Tuples in Python</title>
      <id>https://realpython.com/courses/lists-tuples-python/</id>
      <link href="https://realpython.com/courses/lists-tuples-python/"/>
      <updated>2019-09-03T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll cover the important characteristics of lists and tuples in Python 3. You&#39;ll learn how to define them and how to manipulate them. When you&#39;re finished, you&#39;ll have a good feel for when and how to use these object types in a Python program.</summary>
      <content type="html">
        &lt;p&gt;In this course, you&amp;rsquo;ll learn about working with lists and tuples. &lt;strong&gt;Lists&lt;/strong&gt; and &lt;strong&gt;tuples&lt;/strong&gt; are arguably Python&amp;rsquo;s most versatile, useful &lt;a href=&quot;https://realpython.com/python-data-types/&quot;&gt;data types&lt;/a&gt;. You&amp;rsquo;ll find them in virtually every non-trivial Python program.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here&amp;rsquo;s what you&amp;rsquo;ll learn in this tutorial:&lt;/strong&gt; You&amp;rsquo;ll cover the important characteristics of lists and tuples. You&amp;rsquo;ll learn how to define them and how to manipulate them.  When you&amp;rsquo;re finished, you&amp;rsquo;ll have a good feel for when and how to use these object types in a Python program.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;&lt;i class=&quot;fa fa-graduation-cap&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt; Take the Quiz:&lt;/strong&gt; Test your knowledge with our interactive “Python Lists and Tuples” quiz. Upon completion you will receive a score so you can track your learning progress over time:&lt;/p&gt;&lt;p class=&quot;text-center my-2&quot;&gt;&lt;a class=&quot;btn btn-primary&quot; href=&quot;/quizzes/python-lists-tuples/&quot; target=&quot;_blank&quot;&gt;Take the Quiz »&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Natural Language Processing With spaCy in Python</title>
      <id>https://realpython.com/natural-language-processing-spacy-python/</id>
      <link href="https://realpython.com/natural-language-processing-spacy-python/"/>
      <updated>2019-09-02T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how to use spaCy. This free and open-source library for Natural Language Processing (NLP) in Python has a lot of built-in capabilities and is becoming increasingly popular for processing and analyzing data in NLP.</summary>
      <content type="html">
        &lt;p&gt;&lt;strong&gt;spaCy&lt;/strong&gt; is a free and open-source library for &lt;strong&gt;Natural Language Processing&lt;/strong&gt; (NLP) in Python with a lot of in-built capabilities. It&amp;rsquo;s becoming increasingly popular for processing and analyzing data in NLP. Unstructured textual data is produced at a large scale, and it&amp;rsquo;s important to process and derive insights from unstructured data. To do that, you need to represent the data in a format that can be understood by computers. NLP can help you do that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this tutorial, you&amp;rsquo;ll learn:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What the foundational terms and concepts in NLP are&lt;/li&gt;
&lt;li&gt;How to implement those concepts in spaCy&lt;/li&gt;
&lt;li&gt;How to customize and extend built-in functionalities in spaCy&lt;/li&gt;
&lt;li&gt;How to perform basic statistical analysis on a text&lt;/li&gt;
&lt;li&gt;How to create a pipeline to process unstructured text&lt;/li&gt;
&lt;li&gt;How to parse a sentence and extract meaningful insights from it&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;what-are-nlp-and-spacy&quot;&gt;What Are NLP and spaCy?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;NLP&lt;/strong&gt; is a subfield of &lt;strong&gt;Artificial Intelligence&lt;/strong&gt; and is concerned with interactions between computers and human languages. NLP is the process of analyzing, understanding, and deriving meaning from human languages for computers.&lt;/p&gt;
&lt;p&gt;NLP helps you extract insights from unstructured text and has several use cases, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Automatic_summarization&quot;&gt;Automatic summarization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Named-entity_recognition&quot;&gt;Named entity recognition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Question_answering&quot;&gt;Question answering systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Sentiment_analysis&quot;&gt;Sentiment analysis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;spaCy is a free, open-source library for NLP in Python. It&amp;rsquo;s written in &lt;a href=&quot;https://cython.org/&quot;&gt;Cython&lt;/a&gt; and is designed to build information extraction or natural language understanding systems. It&amp;rsquo;s built for production use and provides a concise and user-friendly API.&lt;/p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll install spaCy and then download data and models for the English language.&lt;/p&gt;
&lt;h3 id=&quot;how-to-install-spacy&quot;&gt;How to Install spaCy&lt;/h3&gt;
&lt;p&gt;spaCy can be installed using &lt;strong&gt;&lt;code&gt;pip&lt;/code&gt;&lt;/strong&gt;, a Python package manager. You can use a &lt;strong&gt;virtual environment&lt;/strong&gt; to avoid depending on system-wide packages. To learn more about virtual environments and &lt;code&gt;pip&lt;/code&gt;, check out &lt;a href=&quot;https://realpython.com/what-is-pip/&quot;&gt;What Is Pip? A Guide for New Pythonistas&lt;/a&gt; and &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;Create a new 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 env
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Activate this virtual environment and install spaCy:&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; ./env/bin/activate
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pip install spacy
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;how-to-download-models-and-data&quot;&gt;How to Download Models and Data&lt;/h3&gt;
&lt;p&gt;spaCy has &lt;a href=&quot;https://spaCy.io/models&quot;&gt;different types&lt;/a&gt; of models. The default model for the English language is &lt;code&gt;en_core_web_sm&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Activate the virtual environment created in the previous step and download models and data for the English language:&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 spacy download en_core_web_sm
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verify if the download was successful or not by loading it:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;spacy&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;en_core_web_sm&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the &lt;code&gt;nlp&lt;/code&gt; object is created, then it means that spaCy was installed and that models and data were successfully downloaded.&lt;/p&gt;
&lt;h2 id=&quot;using-spacy&quot;&gt;Using spaCy&lt;/h2&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll use spaCy for a given input string and a text file. Load the language model instance in spaCy:&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;spacy&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;en_core_web_sm&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, the &lt;code&gt;nlp&lt;/code&gt; object is a language model instance. You can assume that, throughout this tutorial, &lt;code&gt;nlp&lt;/code&gt; refers to the language model loaded by &lt;code&gt;en_core_web_sm&lt;/code&gt;. Now you can use spaCy to read a string or a text file.&lt;/p&gt;
&lt;h3 id=&quot;how-to-read-a-string&quot;&gt;How to Read a String&lt;/h3&gt;
&lt;p&gt;You can use spaCy to create a processed &lt;a href=&quot;https://spaCy.io/api/doc&quot;&gt;Doc&lt;/a&gt; object, which is a container for accessing linguistic annotations, for a given input 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;n&quot;&gt;introduction_text&lt;/span&gt; &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;This tutorial is about Natural&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; Language Processing in Spacy.&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;introduction_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;introduction_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Extract tokens for the given doc&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;token&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;introduction_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;This&amp;#39;, &amp;#39;tutorial&amp;#39;, &amp;#39;is&amp;#39;, &amp;#39;about&amp;#39;, &amp;#39;Natural&amp;#39;, &amp;#39;Language&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Processing&amp;#39;, &amp;#39;in&amp;#39;, &amp;#39;Spacy&amp;#39;, &amp;#39;.&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above example, notice how the text is converted to an object that is understood by spaCy. You can use this method to convert any text into a processed &lt;code&gt;Doc&lt;/code&gt; object and deduce attributes, which will be covered in the coming sections.&lt;/p&gt;
&lt;h3 id=&quot;how-to-read-a-text-file&quot;&gt;How to Read a Text File&lt;/h3&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll create a processed &lt;a href=&quot;https://spaCy.io/api/doc&quot;&gt;Doc&lt;/a&gt; object for a text file:&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;file_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;introduction.txt&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;introduction_file_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;introduction_file_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;introduction_file_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Extract tokens for the given doc&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;token&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;introduction_file_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;This&amp;#39;, &amp;#39;tutorial&amp;#39;, &amp;#39;is&amp;#39;, &amp;#39;about&amp;#39;, &amp;#39;Natural&amp;#39;, &amp;#39;Language&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Processing&amp;#39;, &amp;#39;in&amp;#39;, &amp;#39;Spacy&amp;#39;, &amp;#39;.&amp;#39;, &amp;#39;\n&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is how you can convert a text file into a processed &lt;code&gt;Doc&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; &lt;/p&gt;
&lt;p&gt;You can assume that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Variable names ending with the suffix &lt;strong&gt;&lt;code&gt;_text&lt;/code&gt;&lt;/strong&gt; are &lt;strong&gt;&lt;a href=&quot;https://realpython.com/python-encodings-guide/&quot;&gt;Unicode&lt;/a&gt; string objects&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Variable name ending with the suffix &lt;strong&gt;&lt;code&gt;_doc&lt;/code&gt;&lt;/strong&gt; are &lt;strong&gt;spaCy&amp;rsquo;s language model objects&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;sentence-detection&quot;&gt;Sentence Detection&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Sentence Detection&lt;/strong&gt; is the process of locating the start and end of sentences in a given text. This allows you to you divide a text into linguistically meaningful units. You&amp;rsquo;ll use these units when you&amp;rsquo;re processing your text to perform tasks such as &lt;strong&gt;part of speech tagging&lt;/strong&gt; and &lt;strong&gt;entity extraction&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In spaCy, the &lt;code&gt;sents&lt;/code&gt; property is used to extract sentences. Here&amp;rsquo;s how you would extract the total number of sentences and the sentences for a given input text:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_text&lt;/span&gt; &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;Gus Proto is a Python developer currently&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;              &lt;span class=&quot;s1&quot;&gt;&amp;#39; working for a London-based Fintech&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;              &lt;span class=&quot;s1&quot;&gt;&amp;#39; company. He is interested in learning&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;              &lt;span class=&quot;s1&quot;&gt;&amp;#39; Natural Language Processing.&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;about_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sentences&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;about_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sents&lt;/span&gt;&lt;span class=&quot;p&quot;&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;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sentences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&lt;/span&gt;
&lt;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;sentence&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sentences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sentence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Gus Proto is a Python developer currently working for a&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;London-based Fintech company.&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;He is interested in learning Natural Language Processing.&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above example, spaCy is correctly able to identify sentences in the English language, using a full stop(&lt;code&gt;.&lt;/code&gt;) as the sentence delimiter. You can also customize the sentence detection to detect sentences on custom delimiters.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example, where an ellipsis(&lt;code&gt;...&lt;/code&gt;) is used as the delimiter:&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;set_custom_boundaries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Adds support to use `...` as the delimiter for sentence detection&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;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&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;s1&quot;&gt;&amp;#39;...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&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;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_sent_start&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&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;ellipsis_text&lt;/span&gt; &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;Gus, can you, ... never mind, I forgot&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                 &lt;span class=&quot;s1&quot;&gt;&amp;#39; what I was saying. So, do you think&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                 &lt;span class=&quot;s1&quot;&gt;&amp;#39; we should ...&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;c1&quot;&gt;# Load a new model instance&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_nlp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;en_core_web_sm&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;custom_nlp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_custom_boundaries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;parser&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;custom_ellipsis_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ellipsis_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_ellipsis_sentences&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;custom_ellipsis_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sents&lt;/span&gt;&lt;span class=&quot;p&quot;&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;sentence&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_ellipsis_sentences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sentence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Gus, can you, ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;never mind, I forgot what I was saying.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;So, do you think we should ...&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;# Sentence Detection with no customization&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ellipsis_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ellipsis_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ellipsis_sentences&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;ellipsis_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sents&lt;/span&gt;&lt;span class=&quot;p&quot;&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;sentence&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ellipsis_sentences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sentence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Gus, can you, ... never mind, I forgot what I was saying.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;So, do you think we should ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that &lt;code&gt;custom_ellipsis_sentences&lt;/code&gt; contain three sentences, whereas &lt;code&gt;ellipsis_sentences&lt;/code&gt; contains two sentences. These sentences are still obtained via the &lt;code&gt;sents&lt;/code&gt; attribute, as you saw before.&lt;/p&gt;
&lt;h2 id=&quot;tokenization-in-spacy&quot;&gt;Tokenization in spaCy&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Tokenization&lt;/strong&gt; is the next step after sentence detection. It allows you to identify the basic units in your text. These basic units are called &lt;strong&gt;tokens&lt;/strong&gt;. Tokenization is useful because it breaks a text into meaningful units. These units are used for further analysis, like part of speech tagging.&lt;/p&gt;
&lt;p&gt;In spaCy, you can print tokens by iterating on the &lt;code&gt;Doc&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;about_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Gus 0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Proto 4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is 10&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a 13&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Python 15&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;developer 22&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;currently 32&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;working 42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;for 50&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a 54&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;London 56&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;- 62&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;based 63&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fintech 69&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;company 77&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;. 84&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;He 86&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is 89&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;interested 92&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;in 103&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;learning 106&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Natural 115&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Language 123&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Processing 132&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;. 142&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note how spaCy preserves the &lt;strong&gt;starting index&lt;/strong&gt; of the tokens. It&amp;rsquo;s useful for in-place word replacement. spaCy provides &lt;a href=&quot;https://spacy.io/api/token#attributes&quot;&gt;various attributes&lt;/a&gt; for the &lt;code&gt;Token&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;about_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text_with_ws&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;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_punct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_space&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;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Gus 0 Gus  True False False Xxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Proto 4 Proto  True False False Xxxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is 10 is  True False False xx True&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a 13 a  True False False x True&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Python 15 Python  True False False Xxxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;developer 22 developer  True False False xxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;currently 32 currently  True False False xxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;working 42 working  True False False xxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;for 50 for  True False False xxx True&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a 54 a  True False False x True&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;London 56 London True False False Xxxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;- 62 - False True False - False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;based 63 based  True False False xxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fintech 69 Fintech  True False False Xxxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;company 77 company True False False xxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;. 84 .  False True False . False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;He 86 He  True False False Xx True&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is 89 is  True False False xx True&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;interested 92 interested  True False False xxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;in 103 in  True False False xx True&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;learning 106 learning  True False False xxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Natural 115 Natural  True False False Xxxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Language 123 Language  True False False Xxxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Processing 132 Processing True False False Xxxxx False&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;. 142 . False True False . False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, some of the commonly required attributes are accessed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;text_with_ws&lt;/code&gt;&lt;/strong&gt; prints token text with trailing space (if present).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;is_alpha&lt;/code&gt;&lt;/strong&gt; detects if the token consists of alphabetic characters or not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;is_punct&lt;/code&gt;&lt;/strong&gt; detects if the token is a punctuation symbol or not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;is_space&lt;/code&gt;&lt;/strong&gt; detects if the token is a space or not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;shape_&lt;/code&gt;&lt;/strong&gt; prints out the shape of the word.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;is_stop&lt;/code&gt;&lt;/strong&gt; detects if the token is a stop word or not.&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 learn more about &lt;strong&gt;stop words&lt;/strong&gt; in the next section.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can also customize the tokenization process to detect tokens on custom characters. This is often used for hyphenated words, which are words joined with hyphen. For example, &amp;ldquo;London-based&amp;rdquo; is a hyphenated word.&lt;/p&gt;
&lt;p&gt;spaCy allows you to customize tokenization by updating the &lt;code&gt;tokenizer&lt;/code&gt; property on the &lt;code&gt;nlp&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;re&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;spacy&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;spacy.tokenizer&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tokenizer&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_nlp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;en_core_web_sm&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;prefix_re&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spacy&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;compile_prefix_regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_nlp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Defaults&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefixes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffix_re&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spacy&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;compile_suffix_regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_nlp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Defaults&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffixes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;infix_re&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&amp;#39;[-~]&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;customize_tokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Adds support to use `-` as the delimiter for tokenization&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;Tokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vocab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix_search&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix_re&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                     &lt;span class=&quot;n&quot;&gt;suffix_search&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffix_re&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                     &lt;span class=&quot;n&quot;&gt;infix_finditer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;infix_re&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;finditer&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;token_match&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;gp&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_nlp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenizer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customize_tokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_tokenizer_about_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;token&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_tokenizer_about_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Gus&amp;#39;, &amp;#39;Proto&amp;#39;, &amp;#39;is&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;Python&amp;#39;, &amp;#39;developer&amp;#39;, &amp;#39;currently&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;working&amp;#39;, &amp;#39;for&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;London&amp;#39;, &amp;#39;-&amp;#39;, &amp;#39;based&amp;#39;, &amp;#39;Fintech&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;company&amp;#39;, &amp;#39;.&amp;#39;, &amp;#39;He&amp;#39;, &amp;#39;is&amp;#39;, &amp;#39;interested&amp;#39;, &amp;#39;in&amp;#39;, &amp;#39;learning&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Natural&amp;#39;, &amp;#39;Language&amp;#39;, &amp;#39;Processing&amp;#39;, &amp;#39;.&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In order for you to customize, you can pass various parameters to the &lt;code&gt;Tokenizer&lt;/code&gt; class:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;nlp.vocab&lt;/code&gt;&lt;/strong&gt; is a storage container for special cases and is used to handle cases like contractions and emoticons.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;prefix_search&lt;/code&gt;&lt;/strong&gt; is the function that is used to handle preceding punctuation, such as opening parentheses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;infix_finditer&lt;/code&gt;&lt;/strong&gt; is the function that is used to handle non-whitespace separators, such as hyphens.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;suffix_search&lt;/code&gt;&lt;/strong&gt; is the function that is used to handle succeeding punctuation, such as closing parentheses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;token_match&lt;/code&gt;&lt;/strong&gt; is an optional boolean function that is used to match strings that should never be split. It overrides the previous rules and is useful for entities like URLs or numbers.&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; spaCy already detects hyphenated words as individual tokens. The above code is just an example to show how tokenization can be customized. It can be used for any other character.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;stop-words&quot;&gt;Stop Words&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Stop words&lt;/strong&gt; are the most common words in a language. In the English language, some examples of stop words are &lt;code&gt;the&lt;/code&gt;, &lt;code&gt;are&lt;/code&gt;, &lt;code&gt;but&lt;/code&gt;, and &lt;code&gt;they&lt;/code&gt;. Most sentences need to contain stop words in order to be full sentences that make sense.&lt;/p&gt;
&lt;p&gt;Generally, stop words are removed because they aren&amp;rsquo;t significant and distort the word frequency analysis. spaCy has a list of stop words for the English language:&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;spacy&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spacy_stopwords&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop_words&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STOP_WORDS&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;spacy_stopwords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;326&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;stop_word&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spacy_stopwords&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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop_word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;using&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;becomes&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;had&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;itself&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;once&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;often&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;herein&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;who&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;too&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can remove stop words from the input text:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;about_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Gus&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Proto&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Python&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;developer&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;currently&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;working&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;London&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;based&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fintech&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;company&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;interested&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;learning&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Natural&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Language&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Processing&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Stop words like &lt;code&gt;is&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;the&lt;/code&gt;, and &lt;code&gt;in&lt;/code&gt; are not printed in the output above. You can also create a list of tokens not containing stop words:&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;about_no_stopword_doc&lt;/span&gt; &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;token&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;about_doc&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_stop&lt;/span&gt;&lt;span class=&quot;p&quot;&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;about_no_stopword_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[Gus, Proto, Python, developer, currently, working, London,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-, based, Fintech, company, ., interested, learning, Natural,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Language, Processing, .]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;about_no_stopword_doc&lt;/code&gt; can be joined with spaces to form a sentence with no stop words.&lt;/p&gt;
&lt;h2 id=&quot;lemmatization&quot;&gt;Lemmatization&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Lemmatization&lt;/strong&gt; is the process of reducing inflected forms of a word while still ensuring that the reduced form belongs to the language. This reduced form or root word is called a &lt;strong&gt;lemma&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example, &lt;em&gt;organizes&lt;/em&gt;, &lt;em&gt;organized&lt;/em&gt; and &lt;em&gt;organizing&lt;/em&gt; are all forms of &lt;em&gt;organize&lt;/em&gt;. Here, &lt;em&gt;organize&lt;/em&gt; is the lemma. The inflection of a word allows you to express different grammatical categories like tense (&lt;em&gt;organized&lt;/em&gt; vs &lt;em&gt;organize&lt;/em&gt;), number (&lt;em&gt;trains&lt;/em&gt; vs &lt;em&gt;train&lt;/em&gt;), and so on. Lemmatization is necessary because it helps you reduce the inflected forms of a word so that they can be analyzed as a single item. It can also help you &lt;strong&gt;normalize&lt;/strong&gt; the text.&lt;/p&gt;
&lt;p&gt;spaCy has the attribute &lt;code&gt;lemma_&lt;/code&gt; on the &lt;code&gt;Token&lt;/code&gt; class. This attribute has the lemmatized form of a token:&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;conference_help_text&lt;/span&gt; &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;Gus is helping organize a developer&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39;conference on Applications of Natural Language&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; Processing. He keeps organizing local Python meetups&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; and several internal talks at his workplace.&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;conference_help_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conference_help_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conference_help_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lemma_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Gus Gus&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is be&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;helping help&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;organize organize&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a a&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;developer developer&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;conference conference&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;on on&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Applications Applications&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;of of&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Natural Natural&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Language Language&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Processing Processing&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;. .&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;He -PRON-&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;keeps keep&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;organizing organize&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;local local&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Python Python&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;meetups meetup&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;and and&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;several several&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;internal internal&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;talks talk&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;at at&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;his -PRON-&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;workplace workplace&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;. .&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, &lt;code&gt;organizing&lt;/code&gt; reduces to its lemma form &lt;code&gt;organize&lt;/code&gt;. If you do not lemmatize the text, then &lt;code&gt;organize&lt;/code&gt; and &lt;code&gt;organizing&lt;/code&gt; will be counted as different tokens, even though they both have a similar meaning. Lemmatization helps you avoid duplicate words that have similar meanings.&lt;/p&gt;
&lt;h2 id=&quot;word-frequency&quot;&gt;Word Frequency&lt;/h2&gt;
&lt;p&gt;You can now convert a given text into tokens and perform statistical analysis over it. This analysis can give you various insights about word patterns, such as common words or unique words in the text:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Counter&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;complete_text&lt;/span&gt; &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;Gus Proto is a Python developer currently&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39;working for a London-based Fintech company. He is&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; interested in learning Natural Language Processing.&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; There is a developer conference happening on 21 July&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; 2019 in London. It is titled &amp;quot;Applications of Natural&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; Language Processing&amp;quot;. There is a helpline number &amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; available at +1-1234567891. Gus is helping organize it.&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; He keeps organizing local Python meetups and several&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; internal talks at his workplace. Gus is also presenting&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; a talk. The talk will introduce the reader about &amp;quot;Use&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; cases of Natural Language Processing in Fintech&amp;quot;.&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; Apart from his work, he is very passionate about music.&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; Gus is learning to play the Piano. He has enrolled &amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; himself in the weekend batch of Great Piano Academy.&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; Great Piano Academy is situated in Mayfair or the City&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; of London and has world-class piano instructors.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;complete_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;complete_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Remove stop words and punctuation symbols&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete_doc&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_stop&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_punct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word_freq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# 5 commonly occurring words with their frequencies&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;common_words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word_freq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;most_common&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;common_words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[(&amp;#39;Gus&amp;#39;, 4), (&amp;#39;London&amp;#39;, 3), (&amp;#39;Natural&amp;#39;, 3), (&amp;#39;Language&amp;#39;, 3), (&amp;#39;Processing&amp;#39;, 3)]&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;# Unique words&lt;/span&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_words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;freq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word_freq&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;freq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&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;unique_words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Proto&amp;#39;, &amp;#39;currently&amp;#39;, &amp;#39;working&amp;#39;, &amp;#39;based&amp;#39;, &amp;#39;company&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;interested&amp;#39;, &amp;#39;conference&amp;#39;, &amp;#39;happening&amp;#39;, &amp;#39;21&amp;#39;, &amp;#39;July&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;2019&amp;#39;, &amp;#39;titled&amp;#39;, &amp;#39;Applications&amp;#39;, &amp;#39;helpline&amp;#39;, &amp;#39;number&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;available&amp;#39;, &amp;#39;+1&amp;#39;, &amp;#39;1234567891&amp;#39;, &amp;#39;helping&amp;#39;, &amp;#39;organize&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;keeps&amp;#39;, &amp;#39;organizing&amp;#39;, &amp;#39;local&amp;#39;, &amp;#39;meetups&amp;#39;, &amp;#39;internal&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;talks&amp;#39;, &amp;#39;workplace&amp;#39;, &amp;#39;presenting&amp;#39;, &amp;#39;introduce&amp;#39;, &amp;#39;reader&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Use&amp;#39;, &amp;#39;cases&amp;#39;, &amp;#39;Apart&amp;#39;, &amp;#39;work&amp;#39;, &amp;#39;passionate&amp;#39;, &amp;#39;music&amp;#39;, &amp;#39;play&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;enrolled&amp;#39;, &amp;#39;weekend&amp;#39;, &amp;#39;batch&amp;#39;, &amp;#39;situated&amp;#39;, &amp;#39;Mayfair&amp;#39;, &amp;#39;City&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;world&amp;#39;, &amp;#39;class&amp;#39;, &amp;#39;piano&amp;#39;, &amp;#39;instructors&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By looking at the common words, you can see that the text as a whole is probably about &lt;code&gt;Gus&lt;/code&gt;, &lt;code&gt;London&lt;/code&gt;, or &lt;code&gt;Natural Language Processing&lt;/code&gt;. This way, you can take any unstructured text and perform statistical analysis to know what it&amp;rsquo;s about.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s another example of the same text with stop words:&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;words_all&lt;/span&gt; &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;token&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete_doc&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_punct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word_freq_all&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words_all&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# 5 commonly occurring words with their frequencies&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;common_words_all&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word_freq_all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;most_common&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;common_words_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[(&amp;#39;is&amp;#39;, 10), (&amp;#39;a&amp;#39;, 5), (&amp;#39;in&amp;#39;, 5), (&amp;#39;Gus&amp;#39;, 4), (&amp;#39;of&amp;#39;, 4)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Four out of five of the most common words are stop words, which don&amp;rsquo;t tell you much about the text. If you consider stop words while doing word frequency analysis, then you won&amp;rsquo;t be able to derive meaningful insights from the input text. This is why removing stop words is so important.&lt;/p&gt;
&lt;h2 id=&quot;part-of-speech-tagging&quot;&gt;Part of Speech Tagging&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Part of speech&lt;/strong&gt; or &lt;strong&gt;POS&lt;/strong&gt; is a grammatical role that explains how a particular word is used in a sentence. There are eight parts of speech:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Noun&lt;/li&gt;
&lt;li&gt;Pronoun&lt;/li&gt;
&lt;li&gt;Adjective&lt;/li&gt;
&lt;li&gt;Verb&lt;/li&gt;
&lt;li&gt;Adverb&lt;/li&gt;
&lt;li&gt;Preposition&lt;/li&gt;
&lt;li&gt;Conjunction&lt;/li&gt;
&lt;li&gt;Interjection&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part of speech tagging&lt;/strong&gt; is the process of assigning a &lt;strong&gt;POS tag&lt;/strong&gt; to each token depending on its usage in the sentence. POS tags are useful for assigning a syntactic category like &lt;strong&gt;noun&lt;/strong&gt; or &lt;strong&gt;verb&lt;/strong&gt; to each word.&lt;/p&gt;
&lt;p&gt;In spaCy, POS tags are available as an attribute on the &lt;code&gt;Token&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;about_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tag_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;spacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;explain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tag_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Gus NNP PROPN noun, proper singular&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Proto NNP PROPN noun, proper singular&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is VBZ VERB verb, 3rd person singular present&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a DT DET determiner&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Python NNP PROPN noun, proper singular&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;developer NN NOUN noun, singular or mass&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;currently RB ADV adverb&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;working VBG VERB verb, gerund or present participle&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;for IN ADP conjunction, subordinating or preposition&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a DT DET determiner&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;London NNP PROPN noun, proper singular&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;- HYPH PUNCT punctuation mark, hyphen&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;based VBN VERB verb, past participle&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fintech NNP PROPN noun, proper singular&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;company NN NOUN noun, singular or mass&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;. . PUNCT punctuation mark, sentence closer&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;He PRP PRON pronoun, personal&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is VBZ VERB verb, 3rd person singular present&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;interested JJ ADJ adjective&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;in IN ADP conjunction, subordinating or preposition&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;learning VBG VERB verb, gerund or present participle&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Natural NNP PROPN noun, proper singular&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Language NNP PROPN noun, proper singular&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Processing NNP PROPN noun, proper singular&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;. . PUNCT punctuation mark, sentence closer&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, two attributes of the &lt;code&gt;Token&lt;/code&gt; class are accessed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;tag_&lt;/code&gt;&lt;/strong&gt; lists the fine-grained part of speech.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;pos_&lt;/code&gt;&lt;/strong&gt; lists the coarse-grained part of speech.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;spacy.explain&lt;/code&gt; gives descriptive details about a particular POS tag. spaCy provides a &lt;a href=&quot;https://spaCy.io/api/annotation#pos-tagging&quot;&gt;complete tag list&lt;/a&gt; along with an explanation for each tag.&lt;/p&gt;
&lt;p&gt;Using POS tags, you can extract a particular category of words:&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;nouns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adjectives&lt;/span&gt; &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;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;about_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pos_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;NOUN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;nouns&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pos_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ADJ&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;adjectives&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;token&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;nouns&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[developer, company]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adjectives&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[interested]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can use this to derive insights, remove the most common nouns, or see which adjectives are used for a particular noun.&lt;/p&gt;
&lt;h2 id=&quot;visualization-using-displacy&quot;&gt;Visualization: Using displaCy&lt;/h2&gt;
&lt;p&gt;spaCy comes with a built-in visualizer called &lt;strong&gt;displaCy&lt;/strong&gt;. You can use it to visualize a &lt;strong&gt;dependency parse&lt;/strong&gt; or &lt;strong&gt;named entities&lt;/strong&gt; in a browser or a &lt;a href=&quot;https://realpython.com/jupyter-notebook-introduction/&quot;&gt;Jupyter notebook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can use displaCy to find POS tags for tokens:&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;spacy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;displacy&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_interest_text&lt;/span&gt; &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;He is interested in learning&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; Natural Language Processing.&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;about_interest_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_interest_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_interest_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;dep&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code will spin a simple web server. You can see the visualization by opening &lt;a href=&quot;http://127.0.0.1:5000&quot;&gt;http://127.0.0.1:5000&lt;/a&gt; in your browser:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/displacy_pos_tags.45059f2bf851.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/displacy_pos_tags.45059f2bf851.png&quot; width=&quot;2630&quot; height=&quot;600&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/displacy_pos_tags.45059f2bf851.png&amp;amp;w=657&amp;amp;sig=a49d6b5a0e5952aea59c0241f61fb09440bb326b 657w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/displacy_pos_tags.45059f2bf851.png&amp;amp;w=1315&amp;amp;sig=858218e45ae1e23a87ad42204154aeae77c9cc0c 1315w, https://files.realpython.com/media/displacy_pos_tags.45059f2bf851.png 2630w&quot; sizes=&quot;75vw&quot; alt=&quot;Displacy: Part of Speech Tagging Demo&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;displaCy: Part of Speech Tagging Demo&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;In the image above, each token is assigned a POS tag written just below the token.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Here&amp;rsquo;s how you can use displaCy in a Jupyter notebook:&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;displacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_interest_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;dep&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jupyter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h2 id=&quot;preprocessing-functions&quot;&gt;Preprocessing Functions&lt;/h2&gt;
&lt;p&gt;You can create a &lt;strong&gt;preprocessing function&lt;/strong&gt; that takes text as input and applies the following operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lowercases the text&lt;/li&gt;
&lt;li&gt;Lemmatizes each token&lt;/li&gt;
&lt;li&gt;Removes punctuation symbols&lt;/li&gt;
&lt;li&gt;Removes stop words&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A preprocessing function converts text to an analyzable format. It&amp;rsquo;s necessary for most NLP tasks. Here&amp;rsquo;s an example:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_token_allowed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;sd&quot;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        Only allow valid tokens which are not stop words&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        and punctuation symbols.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_stop&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_punct&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;kc&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;True&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;preprocess_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Reduce token to its lowercase lemma form&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;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lemma_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&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;lower&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;complete_filtered_tokens&lt;/span&gt; &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;preprocess_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&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;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete_doc&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_token_allowed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;complete_filtered_tokens&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;gus&amp;#39;, &amp;#39;proto&amp;#39;, &amp;#39;python&amp;#39;, &amp;#39;developer&amp;#39;, &amp;#39;currently&amp;#39;, &amp;#39;work&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;london&amp;#39;, &amp;#39;base&amp;#39;, &amp;#39;fintech&amp;#39;, &amp;#39;company&amp;#39;, &amp;#39;interested&amp;#39;, &amp;#39;learn&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;natural&amp;#39;, &amp;#39;language&amp;#39;, &amp;#39;processing&amp;#39;, &amp;#39;developer&amp;#39;, &amp;#39;conference&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;happen&amp;#39;, &amp;#39;21&amp;#39;, &amp;#39;july&amp;#39;, &amp;#39;2019&amp;#39;, &amp;#39;london&amp;#39;, &amp;#39;title&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;applications&amp;#39;, &amp;#39;natural&amp;#39;, &amp;#39;language&amp;#39;, &amp;#39;processing&amp;#39;, &amp;#39;helpline&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;number&amp;#39;, &amp;#39;available&amp;#39;, &amp;#39;+1&amp;#39;, &amp;#39;1234567891&amp;#39;, &amp;#39;gus&amp;#39;, &amp;#39;help&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;organize&amp;#39;, &amp;#39;keep&amp;#39;, &amp;#39;organize&amp;#39;, &amp;#39;local&amp;#39;, &amp;#39;python&amp;#39;, &amp;#39;meetup&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;internal&amp;#39;, &amp;#39;talk&amp;#39;, &amp;#39;workplace&amp;#39;, &amp;#39;gus&amp;#39;, &amp;#39;present&amp;#39;, &amp;#39;talk&amp;#39;, &amp;#39;talk&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;introduce&amp;#39;, &amp;#39;reader&amp;#39;, &amp;#39;use&amp;#39;, &amp;#39;case&amp;#39;, &amp;#39;natural&amp;#39;, &amp;#39;language&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;processing&amp;#39;, &amp;#39;fintech&amp;#39;, &amp;#39;apart&amp;#39;, &amp;#39;work&amp;#39;, &amp;#39;passionate&amp;#39;, &amp;#39;music&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;gus&amp;#39;, &amp;#39;learn&amp;#39;, &amp;#39;play&amp;#39;, &amp;#39;piano&amp;#39;, &amp;#39;enrol&amp;#39;, &amp;#39;weekend&amp;#39;, &amp;#39;batch&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;great&amp;#39;, &amp;#39;piano&amp;#39;, &amp;#39;academy&amp;#39;, &amp;#39;great&amp;#39;, &amp;#39;piano&amp;#39;, &amp;#39;academy&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;situate&amp;#39;, &amp;#39;mayfair&amp;#39;, &amp;#39;city&amp;#39;, &amp;#39;london&amp;#39;, &amp;#39;world&amp;#39;, &amp;#39;class&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;piano&amp;#39;, &amp;#39;instructor&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that the &lt;code&gt;complete_filtered_tokens&lt;/code&gt; does not contain any stop word or punctuation symbols and consists of lemmatized lowercase tokens.&lt;/p&gt;
&lt;h2 id=&quot;rule-based-matching-using-spacy&quot;&gt;Rule-Based Matching Using spaCy&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Rule-based matching&lt;/strong&gt; is one of the steps in extracting information from unstructured text. It&amp;rsquo;s used to identify and extract tokens and phrases according to patterns (such as lowercase) and grammatical features (such as part of speech).&lt;/p&gt;
&lt;p&gt;Rule-based matching can use &lt;a href=&quot;https://en.wikipedia.org/wiki/Regular_expression&quot;&gt;regular expressions&lt;/a&gt; to extract entities (such as phone numbers) from an unstructured text. It&amp;rsquo;s different from extracting text using regular expressions only in the sense that regular expressions don&amp;rsquo;t consider the lexical and grammatical attributes of the text.&lt;/p&gt;
&lt;p&gt;With rule-based matching, you can extract a first name and a last name, which are always &lt;strong&gt;proper nouns&lt;/strong&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;spacy.matcher&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Matcher&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Matcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vocab&lt;/span&gt;&lt;span class=&quot;p&quot;&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;extract_full_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp_doc&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;pattern&lt;/span&gt; &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;POS&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;PROPN&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;s1&quot;&gt;&amp;#39;POS&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;PROPN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;matcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;FULL_NAME&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pattern&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;matches&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp_doc&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;match_id&lt;/span&gt;&lt;span class=&quot;p&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;end&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matches&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;span&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp_doc&lt;/span&gt;&lt;span class=&quot;p&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;end&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;span&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;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;extract_full_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Gus Proto&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, &lt;code&gt;pattern&lt;/code&gt; is a list of objects that defines the combination of tokens to be matched. Both POS tags in it are &lt;code&gt;PROPN&lt;/code&gt; (proper noun). So, the &lt;code&gt;pattern&lt;/code&gt; consists of two objects in which the POS tags for both tokens should be &lt;code&gt;PROPN&lt;/code&gt;. This pattern is then added to &lt;code&gt;Matcher&lt;/code&gt; using &lt;code&gt;FULL_NAME&lt;/code&gt; and the the &lt;code&gt;match_id&lt;/code&gt;. Finally, matches are obtained with their starting and end indexes.&lt;/p&gt;
&lt;p&gt;You can also use rule-based matching to extract phone numbers:&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;spacy.matcher&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Matcher&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Matcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vocab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conference_org_text&lt;/span&gt; &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;There is a developer conference&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39;happening on 21 July 2019 in London. It is titled&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;quot;Applications of Natural Language Processing&amp;quot;.&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; There is a helpline number available&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; at (123) 456-789&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;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;extract_phone_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp_doc&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;pattern&lt;/span&gt; &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;ORTH&amp;#39;&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;s1&quot;&gt;&amp;#39;SHAPE&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ddd&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;               &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;ORTH&amp;#39;&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;s1&quot;&gt;&amp;#39;SHAPE&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ddd&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;               &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;ORTH&amp;#39;&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;OP&amp;#39;&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;gp&quot;&gt;... &lt;/span&gt;               &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;SHAPE&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ddd&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;matcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;PHONE_NUMBER&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pattern&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;matches&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp_doc&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;match_id&lt;/span&gt;&lt;span class=&quot;p&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;end&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matches&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;span&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp_doc&lt;/span&gt;&lt;span class=&quot;p&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;end&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;span&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;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;conference_org_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conference_org_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extract_phone_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conference_org_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;(123) 456-789&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, only the pattern is updated in order to match phone numbers from the previous example. Here, some attributes of the token are also used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ORTH&lt;/code&gt;&lt;/strong&gt; gives the exact text of the token.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SHAPE&lt;/code&gt;&lt;/strong&gt; transforms the token string to show orthographic features.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;OP&lt;/code&gt;&lt;/strong&gt; defines operators. Using &lt;code&gt;?&lt;/code&gt; as a value means that the pattern is optional, meaning it can match 0 or 1 times.&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; For simplicity, phone numbers are assumed to be of a particular format: &lt;code&gt;(123) 456-789&lt;/code&gt;. You can change this depending on your use case.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Rule-based matching helps you identify and extract tokens and phrases according to lexical patterns (such as lowercase) and grammatical features(such as part of speech).&lt;/p&gt;
&lt;h2 id=&quot;dependency-parsing-using-spacy&quot;&gt;Dependency Parsing Using spaCy&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Dependency parsing&lt;/strong&gt; is the process of extracting the dependency parse of a sentence to represent its grammatical structure. It defines the dependency relationship between &lt;strong&gt;headwords&lt;/strong&gt; and their &lt;strong&gt;dependents&lt;/strong&gt;. The head of a sentence has no dependency and is called the &lt;strong&gt;root of the sentence&lt;/strong&gt;. The &lt;strong&gt;verb&lt;/strong&gt; is usually the head of the sentence. All other words are linked to the headword.&lt;/p&gt;
&lt;p&gt;The dependencies can be mapped in a directed graph representation: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Words are the nodes.&lt;/li&gt;
&lt;li&gt;The grammatical relationships are the edges.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dependency parsing helps you know what role a word plays in the text and how different words relate to each other. It&amp;rsquo;s also used in &lt;strong&gt;shallow parsing&lt;/strong&gt; and named entity recognition.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how you can use dependency parsing to see the relationships between words:&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;piano_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Gus is learning piano&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;piano_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;piano_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;piano_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&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;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tag_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&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;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dep_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Gus NNP learning nsubj&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;is VBZ learning aux&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;learning VBG learning ROOT&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;piano NN learning dobj&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, the sentence contains three relationships:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;nsubj&lt;/code&gt;&lt;/strong&gt; is the subject of the word. Its headword is a verb.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;aux&lt;/code&gt;&lt;/strong&gt; is an auxiliary word. Its headword is a verb.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;dobj&lt;/code&gt;&lt;/strong&gt; is the direct object of the verb. Its headword is a verb.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is a detailed &lt;a href=&quot;https://nlp.stanford.edu/software/dependencies_manual.pdf&quot;&gt;list of relationships&lt;/a&gt; with descriptions. You can use displaCy to visualize the dependency tree:&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;displacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;piano_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;dep&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code will produce a visualization that can be accessed by opening &lt;a href=&quot;http://127.0.0.1:5000&quot;&gt;http://127.0.0.1:5000&lt;/a&gt; in your browser:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/displacy_dependency_parse.de72f9b1d115.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/displacy_dependency_parse.de72f9b1d115.png&quot; width=&quot;1278&quot; height=&quot;596&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/displacy_dependency_parse.de72f9b1d115.png&amp;amp;w=319&amp;amp;sig=111728c07cf2e1f64b8419cfce8a5f880c244d03 319w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/displacy_dependency_parse.de72f9b1d115.png&amp;amp;w=639&amp;amp;sig=f90a72529d7bc2d2dd944af3c02bbf487b65aaf3 639w, https://files.realpython.com/media/displacy_dependency_parse.de72f9b1d115.png 1278w&quot; sizes=&quot;75vw&quot; alt=&quot;Displacy: Dependency Parse Demo&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;displaCy: Dependency Parse Demo&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;This image shows you that the subject of the sentence is the proper noun &lt;code&gt;Gus&lt;/code&gt; and that it has a &lt;code&gt;learn&lt;/code&gt; relationship with &lt;code&gt;piano&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;navigating-the-tree-and-subtree&quot;&gt;Navigating the Tree and Subtree&lt;/h2&gt;
&lt;p&gt;The dependency parse tree has all the properties of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tree_(data_structure)&quot;&gt;tree&lt;/a&gt;. This tree contains information about sentence structure and grammar and can be traversed in different ways to extract relationships.&lt;/p&gt;
&lt;p&gt;spaCy provides attributes like &lt;code&gt;children&lt;/code&gt;, &lt;code&gt;lefts&lt;/code&gt;, &lt;code&gt;rights&lt;/code&gt;, and &lt;code&gt;subtree&lt;/code&gt; to navigate the parse tree:&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;one_line_about_text&lt;/span&gt; &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;Gus Proto is a Python developer&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; currently working for a London-based Fintech company&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;one_line_about_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;one_line_about_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Extract children of `developer`&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;token&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;one_line_about_doc&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;a&amp;#39;, &amp;#39;Python&amp;#39;, &amp;#39;working&amp;#39;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Extract previous neighboring node of `developer`&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;one_line_about_doc&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nbor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Python&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;# Extract next neighboring node of `developer`&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;one_line_about_doc&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nbor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;currently&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;# Extract all tokens on the left of `developer`&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;token&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;one_line_about_doc&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lefts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;a&amp;#39;, &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;c1&quot;&gt;# Extract tokens on the right of `developer`&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;token&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;one_line_about_doc&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;working&amp;#39;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Print subtree of `developer`&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;one_line_about_doc&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subtree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[a, Python, developer, currently, working, for, a, London, -,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;based, Fintech, company]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can construct a function that takes a subtree as an argument and returns a string by merging words in it:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;flatten_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&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;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text_with_ws&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&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;strip&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;c1&quot;&gt;# Print flattened subtree of `developer`&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;flatten_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;one_line_about_doc&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subtree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a Python developer currently working for a London-based Fintech company&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can use this function to print all the tokens in a subtree.&lt;/p&gt;
&lt;h2 id=&quot;shallow-parsing&quot;&gt;Shallow Parsing&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Shallow parsing&lt;/strong&gt;, or &lt;strong&gt;chunking&lt;/strong&gt;, is the process of extracting phrases from unstructured text. Chunking groups adjacent tokens into phrases on the basis of their POS tags. There are some standard well-known chunks such as noun phrases, verb phrases, and prepositional phrases.&lt;/p&gt;
&lt;h3 id=&quot;noun-phrase-detection&quot;&gt;Noun Phrase Detection&lt;/h3&gt;
&lt;p&gt;A noun phrase is a phrase that has a noun as its head. It could also include other kinds of words, such as adjectives, ordinals, determiners. Noun phrases are useful for explaining the context of the sentence. They help you infer &lt;em&gt;what&lt;/em&gt; is being talked about in the sentence.&lt;/p&gt;
&lt;p&gt;spaCy has the property &lt;code&gt;noun_chunks&lt;/code&gt; on &lt;code&gt;Doc&lt;/code&gt; object. You can use it to extract noun phrases:&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;conference_text&lt;/span&gt; &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;There is a developer conference&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; happening on 21 July 2019 in London.&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;conference_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conference_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Extract Noun Phrases&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;chunk&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conference_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noun_chunks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;a developer conference&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;21 July&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;London&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By looking at noun phrases, you can get information about your text. For example, &lt;code&gt;a developer conference&lt;/code&gt; indicates that the text mentions a conference, while the date &lt;code&gt;21 July&lt;/code&gt; lets you know that conference is scheduled for &lt;code&gt;21 July&lt;/code&gt;. You can figure out whether the conference is in the past or the future. &lt;code&gt;London&lt;/code&gt; tells you that the conference is in &lt;code&gt;London&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;verb-phrase-detection&quot;&gt;Verb Phrase Detection&lt;/h3&gt;
&lt;p&gt;A &lt;strong&gt;verb phrase&lt;/strong&gt; is a syntactic unit composed of at least one verb. This verb can be followed by other chunks, such as noun phrases. Verb phrases are useful for understanding the actions that nouns are involved in. &lt;/p&gt;
&lt;p&gt;spaCy has no built-in functionality to extract verb phrases, so you&amp;rsquo;ll need a library called &lt;a href=&quot;https://chartbeat-labs.github.io/textacy/&quot;&gt;&lt;code&gt;textacy&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;You can use &lt;code&gt;pip&lt;/code&gt; to install &lt;code&gt;textacy&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 textacy
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;Now that you have &lt;code&gt;textacy&lt;/code&gt; installed, you can use it to extract verb phrases based on grammar rules:&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;textacy&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_talk_text&lt;/span&gt; &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;The talk will introduce reader about Use&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                   &lt;span class=&quot;s1&quot;&gt;&amp;#39; cases of Natural Language Processing in&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                   &lt;span class=&quot;s1&quot;&gt;&amp;#39; Fintech&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;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;(&amp;lt;VERB&amp;gt;?&amp;lt;ADV&amp;gt;*&amp;lt;VERB&amp;gt;+)&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;about_talk_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_spacy_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_talk_text&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;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;en_core_web_sm&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;verb_phrases&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extract&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pos_regex_matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about_talk_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Print all Verb Phrase&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;chunk&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;verb_phrases&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&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;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;will introduce&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;# Extract Noun Phrase to explain what nouns are involved&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;chunk&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;about_talk_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noun_chunks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The talk&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;reader&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Use cases&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Natural Language Processing&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fintech&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, the verb phrase &lt;code&gt;introduce&lt;/code&gt; indicates that something will be introduced. By looking at noun phrases, you can see that there is a &lt;code&gt;talk&lt;/code&gt; that will &lt;code&gt;introduce&lt;/code&gt; the &lt;code&gt;reader&lt;/code&gt; to &lt;code&gt;use cases&lt;/code&gt; of &lt;code&gt;Natural Language Processing&lt;/code&gt; or &lt;code&gt;Fintech&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The above code extracts all the verb phrases &lt;a href=&quot;https://chartbeat-labs.github.io/textacy/api_reference/information_extraction.html?highlight=pos#textacy.extract.pos_regex_matches&quot;&gt;using a regular expression pattern&lt;/a&gt; of POS tags. You can tweak the pattern for verb phrases depending upon your use case.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In the previous example, you could have also done dependency parsing to see what the &lt;a href=&quot;https://nlp.stanford.edu/software/dependencies_manual.pdf&quot;&gt;relationships&lt;/a&gt; between the words were.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;named-entity-recognition&quot;&gt;Named Entity Recognition&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Named Entity Recognition&lt;/strong&gt; (NER) is the process of locating &lt;strong&gt;named entities&lt;/strong&gt; in unstructured text and then classifying them into pre-defined categories, such as person names, organizations, locations, monetary values, percentages, time expressions, and so on.&lt;/p&gt;
&lt;p&gt;You can use &lt;strong&gt;NER&lt;/strong&gt; to know more about the meaning of your text. For example, you could use it to populate tags for a set of documents in order to improve the keyword search. You could also use it to categorize customer support tickets into relevant categories.&lt;/p&gt;
&lt;p&gt;spaCy has the property &lt;code&gt;ents&lt;/code&gt; on &lt;code&gt;Doc&lt;/code&gt; objects. You can use it to extract named entities:&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;piano_class_text&lt;/span&gt; &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;Great Piano Academy is situated&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; in Mayfair or the City of London and has&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39; world-class piano instructors.&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;piano_class_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;piano_class_text&lt;/span&gt;&lt;span class=&quot;p&quot;&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;ent&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;piano_class_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ent&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;ent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_char&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;ent&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;spacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;explain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ent&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;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Great Piano Academy 0 19 ORG Companies, agencies, institutions, etc.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Mayfair 35 42 GPE Countries, cities, states&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;the City of London 46 64 GPE Countries, cities, states&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above example, &lt;code&gt;ent&lt;/code&gt; is a &lt;a href=&quot;https://spacy.io/api/span&quot;&gt;&lt;code&gt;Span&lt;/code&gt;&lt;/a&gt; object with various attributes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;text&lt;/code&gt;&lt;/strong&gt; gives the Unicode text representation of the entity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;start_char&lt;/code&gt;&lt;/strong&gt; denotes the character offset for the start of the entity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;end_char&lt;/code&gt;&lt;/strong&gt; denotes the character offset for the end of the entity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;label_&lt;/code&gt;&lt;/strong&gt; gives the label of the entity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;spacy.explain&lt;/code&gt; gives descriptive details about an entity label. The spaCy model has a pre-trained &lt;a href=&quot;https://spaCy.io/api/annotation#named-entities&quot;&gt;list of entity classes&lt;/a&gt;. You can use displaCy to visualize these entities:&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;displacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;piano_class_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;ent&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you open &lt;a href=&quot;http://127.0.0.1:5000&quot;&gt;http://127.0.0.1:5000&lt;/a&gt; in your browser, then you can see the visualization:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/displacy_ner.1fba6869638f.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/displacy_ner.1fba6869638f.png&quot; width=&quot;1930&quot; height=&quot;140&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/displacy_ner.1fba6869638f.png&amp;amp;w=482&amp;amp;sig=18b93b0aed61930a6eedd37dbd12fbbce22733d4 482w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/displacy_ner.1fba6869638f.png&amp;amp;w=965&amp;amp;sig=f6b3cfb460053397a23a0eb49ebc22cf05dd15ab 965w, https://files.realpython.com/media/displacy_ner.1fba6869638f.png 1930w&quot; sizes=&quot;75vw&quot; alt=&quot;Displacy: Named Entity Recognition Demo&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;displaCy: Named Entity Recognition Demo&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;You can use NER to redact people&amp;rsquo;s names from a text. For example, you might want to do this in order to hide personal information collected in a survey. You can use spaCy to do that:&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;survey_text&lt;/span&gt; &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;Out of 5 people surveyed, James Robert,&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;               &lt;span class=&quot;s1&quot;&gt;&amp;#39; Julie Fuller and Benjamin Brooks like&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;               &lt;span class=&quot;s1&quot;&gt;&amp;#39; apples. Kelly Cox and Matthew Evans&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;               &lt;span class=&quot;s1&quot;&gt;&amp;#39; like oranges.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;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;replace_person_names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ent_iob&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;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ent_type_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;PERSON&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;[REDACTED] &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;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;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;redact_names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nlp_doc&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;ent&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ents&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;ent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;merge&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;tokens&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;replace_person_names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp_doc&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;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokens&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;survey_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;survey_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;redact_names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;survey_doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Out of 5 people surveyed, [REDACTED] , [REDACTED] and&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39; [REDACTED] like apples. [REDACTED] and [REDACTED]&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39; like oranges.&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, &lt;code&gt;replace_person_names()&lt;/code&gt; uses &lt;code&gt;ent_iob&lt;/code&gt;. It gives the IOB code of the named entity tag using &lt;a href=&quot;https://en.wikipedia.org/wiki/Inside%E2%80%93outside%E2%80%93beginning_(tagging)&quot;&gt;inside-outside-beginning (IOB) tagging&lt;/a&gt;. Here, it can assume a value other than zero, because zero means that no entity tag is set.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;spaCy is a powerful and advanced library that is gaining huge popularity for NLP applications due to its speed, ease of use, accuracy, and extensibility. Congratulations! You now know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What the foundational terms and concepts in NLP are&lt;/li&gt;
&lt;li&gt;How to implement those concepts in spaCy&lt;/li&gt;
&lt;li&gt;How to customize and extend built-in functionalities in spaCy&lt;/li&gt;
&lt;li&gt;How to perform basic statistical analysis on a text&lt;/li&gt;
&lt;li&gt;How to create a pipeline to process unstructured text&lt;/li&gt;
&lt;li&gt;How to parse a sentence and extract meaningful insights from it&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>PyCharm for Productive Python Development (Guide)</title>
      <id>https://realpython.com/pycharm-guide/</id>
      <link href="https://realpython.com/pycharm-guide/"/>
      <updated>2019-08-28T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how you can use PyCharm to be a more productive Python developer. PyCharm makes debugging and visualization easy so you can focus on business logic and just get the job done.</summary>
      <content type="html">
        &lt;p&gt;As a programmer, you should be focused on the business logic and creating useful applications for your users. In doing that, &lt;a href=&quot;https://www.jetbrains.com/pycharm/&quot;&gt;PyCharm&lt;/a&gt; by &lt;a href=&quot;https://www.jetbrains.com/&quot;&gt;JetBrains&lt;/a&gt; saves you a lot of time by taking care of the routine and by making a number of other tasks such as debugging and visualization easy.   &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;Installing PyCharm&lt;/li&gt;
&lt;li&gt;Writing code in PyCharm&lt;/li&gt;
&lt;li&gt;Running your code in PyCharm&lt;/li&gt;
&lt;li&gt;Debugging and testing your code in PyCharm&lt;/li&gt;
&lt;li&gt;Editing an existing project in PyCharm&lt;/li&gt;
&lt;li&gt;Searching and navigating in PyCharm&lt;/li&gt;
&lt;li&gt;Using Version Control in PyCharm&lt;/li&gt;
&lt;li&gt;Using Plugins and External Tools in PyCharm&lt;/li&gt;
&lt;li&gt;Using PyCharm Professional features, such as Django support and Scientific mode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article assumes that you&amp;rsquo;re familiar with Python development and already have some form of Python installed on your system. Python 3.6 will be used for this tutorial. Screenshots and demos provided are for macOS. Because PyCharm runs on all major platforms, you may see slightly different UI elements and may need to modify certain commands.&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;/p&gt;
&lt;p&gt;PyCharm comes in three editions: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/pycharm-edu/&quot;&gt;PyCharm Edu&lt;/a&gt; is free and for educational purposes.  &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/pycharm&quot;&gt;PyCharm Community&lt;/a&gt; is free as well and intended for pure Python development. &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/pycharm&quot;&gt;PyCharm Professional&lt;/a&gt; is paid, has everything the Community edition has and also is very well suited for Web and Scientific development with support for such frameworks as Django and Flask, Database and SQL, and scientific tools such as Jupyter.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For more details on their differences, check out the &lt;a href=&quot;https://www.jetbrains.com/pycharm/features/editions_comparison_matrix.html&quot;&gt;PyCharm Editions Comparison Matrix&lt;/a&gt; by JetBrains. The company also has &lt;a href=&quot;https://www.jetbrains.com/pycharm/buy/#edition=discounts&quot;&gt;special offers&lt;/a&gt; for students, teachers, open source projects, and other cases.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Clone Repo:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/optins/view/alcazar-web-framework/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-alcazar-web-framework&quot; data-focus=&quot;false&quot;&gt;Click here to clone the repo you&#39;ll use&lt;/a&gt; to explore the project-focused features of PyCharm in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;installing-pycharm&quot;&gt;Installing PyCharm&lt;/h2&gt;
&lt;p&gt;This article will use PyCharm Community Edition 2019.1 as it&amp;rsquo;s free and available on every major platform. Only the section about the professional features will use PyCharm Professional Edition 2019.1.  &lt;/p&gt;
&lt;p&gt;The recommended way of installing PyCharm is with the &lt;a href=&quot;https://www.jetbrains.com/toolbox/app/&quot;&gt;JetBrains Toolbox App&lt;/a&gt;. With its help, you&amp;rsquo;ll be able to install different JetBrains products or several versions of the same product, update, rollback, and easily remove any tool when necessary. You&amp;rsquo;ll also be able to quickly open any project in the right IDE and version.&lt;/p&gt;
&lt;p&gt;To install the Toolbox App, refer to the &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/installation-guide.html#toolbox&quot;&gt;documentation&lt;/a&gt; by JetBrains. It will automatically give you the right instructions depending on your OS. In case it didn&amp;rsquo;t recognize your OS correctly, you can always find it from the drop down list on the top right section: &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-jetbrains-os-list.231740335aaa.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/pycharm-jetbrains-os-list.231740335aaa.png&quot; width=&quot;1010&quot; height=&quot;679&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-jetbrains-os-list.231740335aaa.png&amp;amp;w=252&amp;amp;sig=e331b2eb15a3c8b9396327dedc700bd2bcbbc9e3 252w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-jetbrains-os-list.231740335aaa.png&amp;amp;w=505&amp;amp;sig=4a0a0527b968050fb042a0565f5d6970d72ee1f9 505w, https://files.realpython.com/media/pycharm-jetbrains-os-list.231740335aaa.png 1010w&quot; sizes=&quot;75vw&quot; alt=&quot;List of OSes in the JetBrains website&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After installing, launch the app and accept the user agreement. Under the &lt;em&gt;Tools&lt;/em&gt; tab, you&amp;rsquo;ll see a list of available products. Find PyCharm Community there and click &lt;em&gt;Install&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-toolbox-installed-pycharm.cdcf1b52bc02.png&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/pycharm-toolbox-installed-pycharm.cdcf1b52bc02.png&quot; width=&quot;337&quot; height=&quot;537&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-toolbox-installed-pycharm.cdcf1b52bc02.png&amp;amp;w=84&amp;amp;sig=5f1e571c6c7bed958efddaec87d6ac5168713217 84w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-toolbox-installed-pycharm.cdcf1b52bc02.png&amp;amp;w=168&amp;amp;sig=0a76111939657ae01eaa8203b24c0c2e4fff5ee6 168w, https://files.realpython.com/media/pycharm-toolbox-installed-pycharm.cdcf1b52bc02.png 337w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCharm installed with the Toolbox app&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Voilà! You have PyCharm available on your machine. If you don&amp;rsquo;t want to use the Toolbox app, then you can also do a &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/installation-guide.html#standalone&quot;&gt;stand-alone installation of PyCharm&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Launch PyCharm, and you&amp;rsquo;ll see the import settings popup:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-import-settings-popup.4e360260c697.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/pycharm-import-settings-popup.4e360260c697.png&quot; width=&quot;416&quot; height=&quot;156&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-import-settings-popup.4e360260c697.png&amp;amp;w=104&amp;amp;sig=4920753cc035f162c505253937453e1aa7cc4d26 104w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-import-settings-popup.4e360260c697.png&amp;amp;w=208&amp;amp;sig=b65b1226bcc172a811d7cd1e00cd600408fba092 208w, https://files.realpython.com/media/pycharm-import-settings-popup.4e360260c697.png 416w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCharm Import Settings Popup&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PyCharm will automatically detect that this is a fresh install and choose &lt;em&gt;Do not import settings&lt;/em&gt; for you. Click &lt;em&gt;OK&lt;/em&gt;, and PyCharm will ask you to select a keymap scheme. Leave the default and click &lt;em&gt;Next: UI Themes&lt;/em&gt; on the bottom right:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-keymap-scheme.c8115fda9bdd.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/pycharm-keymap-scheme.c8115fda9bdd.png&quot; width=&quot;805&quot; height=&quot;666&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-keymap-scheme.c8115fda9bdd.png&amp;amp;w=201&amp;amp;sig=644595a94c07780a552f76abbfc5fe526b3c9459 201w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-keymap-scheme.c8115fda9bdd.png&amp;amp;w=402&amp;amp;sig=64c348872c1519bc4148e3dbbac2550ed6c0fa30 402w, https://files.realpython.com/media/pycharm-keymap-scheme.c8115fda9bdd.png 805w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCharm Keymap Scheme&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PyCharm will then ask you to choose a dark theme called Darcula or a light theme. Choose whichever you prefer and click &lt;em&gt;Next: Launcher Script&lt;/em&gt;:  &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-set-ui-theme.c48aac8e3fe0.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/pycharm-set-ui-theme.c48aac8e3fe0.png&quot; width=&quot;803&quot; height=&quot;666&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-set-ui-theme.c48aac8e3fe0.png&amp;amp;w=200&amp;amp;sig=6998b85afd9e2ca1503624ba55b904f4051f1ffe 200w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-set-ui-theme.c48aac8e3fe0.png&amp;amp;w=401&amp;amp;sig=a6480f0b0073f0680068828fc2f0f5c8ee55cbdb 401w, https://files.realpython.com/media/pycharm-set-ui-theme.c48aac8e3fe0.png 803w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCharm Set UI Theme Page&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be using the dark theme Darcula throughout this tutorial. You can find and install other themes as &lt;a href=&quot;#using-plugins-and-external-tools-in-pycharm&quot;&gt;plugins&lt;/a&gt;, or you can also &lt;a href=&quot;https://blog.codota.com/5-best-intellij-themes/&quot;&gt;import them&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the next page, leave the defaults and click &lt;em&gt;Next: Featured plugins&lt;/em&gt;. There, PyCharm will show you a list of plugins you may want to install because most users like to use them. Click &lt;em&gt;Start using PyCharm&lt;/em&gt;, and now you are ready to write some code!&lt;/p&gt;
&lt;h2 id=&quot;writing-code-in-pycharm&quot;&gt;Writing Code in PyCharm&lt;/h2&gt;
&lt;p&gt;In PyCharm, you do everything in the context of a &lt;strong&gt;project&lt;/strong&gt;. Thus, the first thing you need to do is create one.&lt;/p&gt;
&lt;p&gt;After installing and opening PyCharm, you are on the welcome screen. Click &lt;em&gt;Create New Project&lt;/em&gt;, and you&amp;rsquo;ll see the &lt;em&gt;New Project&lt;/em&gt; popup:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-new-project.cc35f3aa1056.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/pycharm-new-project.cc35f3aa1056.png&quot; width=&quot;664&quot; height=&quot;480&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-new-project.cc35f3aa1056.png&amp;amp;w=166&amp;amp;sig=6423b68127eae8ca93165323df4884844265f5e3 166w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-new-project.cc35f3aa1056.png&amp;amp;w=332&amp;amp;sig=50d660be9a42904b1161bd76df1ab9ddd77e2132 332w, https://files.realpython.com/media/pycharm-new-project.cc35f3aa1056.png 664w&quot; sizes=&quot;75vw&quot; alt=&quot;New Project in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Specify the project location and expand the &lt;em&gt;Project Interpreter&lt;/em&gt; drop down. Here, you have options to create a new project interpreter or reuse an existing one. Choose &lt;em&gt;New environment using&lt;/em&gt;. Right next to it, you have a drop down list to select one of &lt;em&gt;Virtualenv&lt;/em&gt;, &lt;em&gt;Pipenv&lt;/em&gt;, or &lt;em&gt;Conda&lt;/em&gt;, which are the tools that help to keep dependencies required by different projects separate by creating isolated Python environments for them. &lt;/p&gt;
&lt;p&gt;You are free to select whichever you like, but &lt;em&gt;Virtualenv&lt;/em&gt; is used for this tutorial. If you choose to, you can specify the environment location and choose the base interpreter from the list, which is a list of Python interpreters (such as Python2.7 and Python3.6) installed on your system. Usually, the defaults are fine. Then you have to select boxes to inherit global site-packages to your new environment and make it available to all other projects. Leave them unselected.  &lt;/p&gt;
&lt;p&gt;Click &lt;em&gt;Create&lt;/em&gt; on the bottom right and you will see the new project created:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-project-created.99dffd1d4e9a.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/pycharm-project-created.99dffd1d4e9a.png&quot; width=&quot;1174&quot; height=&quot;734&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-project-created.99dffd1d4e9a.png&amp;amp;w=293&amp;amp;sig=d6394f174acab8ee63eb6ce0360d0174857f7afb 293w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-project-created.99dffd1d4e9a.png&amp;amp;w=587&amp;amp;sig=2fd8ea44cc0ad15f015aab687018ec7ad8861a53 587w, https://files.realpython.com/media/pycharm-project-created.99dffd1d4e9a.png 1174w&quot; sizes=&quot;75vw&quot; alt=&quot;Project created in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You will also see a small &lt;em&gt;Tip of the Day&lt;/em&gt; popup where PyCharm gives you one trick to learn at each startup. Go ahead and close this popup.&lt;/p&gt;
&lt;p&gt;It is now time to start a new Python program. Type &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-n&quot;&gt;N&lt;/kbd&gt;&lt;/span&gt; if you are on Mac 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-insert&quot;&gt;Ins&lt;/kbd&gt;&lt;/span&gt; if you are on Windows or Linux. Then, choose &lt;em&gt;Python File&lt;/em&gt;. You can also select &lt;em&gt;File → New&lt;/em&gt; from the menu. Name the new file &lt;code&gt;guess_game.py&lt;/code&gt; and click &lt;em&gt;OK&lt;/em&gt;. You will see a PyCharm window similar to the following:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-new-file.7ea9902d73ea.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/pycharm-new-file.7ea9902d73ea.png&quot; width=&quot;1172&quot; height=&quot;734&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-new-file.7ea9902d73ea.png&amp;amp;w=293&amp;amp;sig=b1ee432e97d642aea67818cc7280971247196a62 293w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-new-file.7ea9902d73ea.png&amp;amp;w=586&amp;amp;sig=3563b00140a3edd3f1df0e522d5069f6efcb62d3 586w, https://files.realpython.com/media/pycharm-new-file.7ea9902d73ea.png 1172w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCharm New File&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For our test code, let&amp;rsquo;s quickly code up a simple guessing game in which the program chooses a number that the user has to guess. For every guess, the program will tell if the user&amp;rsquo;s guess was smaller or bigger than the secret number. The game ends when the user guesses the number. Here&amp;rsquo;s the code for the game:&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;random&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;randint&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;play&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;n&quot;&gt;random_int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;randint&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;100&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;user_guess&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;What number did we guess (0-100)?&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_guess&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;randint&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;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;You found the number (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{random_int}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;). Congrats!&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;break&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_guess&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;random_int&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;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;Your number is less than the number we guessed.&amp;quot;&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;continue&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;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_guess&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;random_int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;            &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Your number is more than the number we guessed.&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;k&quot;&gt;continue&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &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;23 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Type this code directly rather than copying and pasting. You&amp;rsquo;ll see something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/typing-guess-game.fcaedeb8ece2.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/typing-guess-game.fcaedeb8ece2.gif&quot; width=&quot;528&quot; height=&quot;480&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/typing-guess-game.fcaedeb8ece2.gif&amp;amp;w=132&amp;amp;sig=7e5eb20fb9ae97b1cea80380f9ad00f35dd76707 132w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/typing-guess-game.fcaedeb8ece2.gif&amp;amp;w=264&amp;amp;sig=eb242bca301203a38741a986d7847cf0f3ef4cff 264w, https://files.realpython.com/media/typing-guess-game.fcaedeb8ece2.gif 528w&quot; sizes=&quot;75vw&quot; alt=&quot;Typing Guessing Game&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, PyCharm provides &lt;a href=&quot;https://www.jetbrains.com/pycharm/features/coding_assistance.html&quot;&gt;Intelligent Coding Assistance&lt;/a&gt; with code completion, code inspections, on-the-fly error highlighting, and quick-fix suggestions. In particular, note how when you typed &lt;code&gt;main&lt;/code&gt; and then hit tab, PyCharm auto-completed the whole &lt;code&gt;main&lt;/code&gt; clause for you. &lt;/p&gt;
&lt;p&gt;Also note how, if you forget to type &lt;code&gt;if&lt;/code&gt; before the condition, append &lt;code&gt;.if&lt;/code&gt;, and then hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-tab&quot;&gt;Tab&lt;/kbd&gt;&lt;/span&gt;, PyCharm fixes the &lt;code&gt;if&lt;/code&gt; clause for you. The same is true with &lt;code&gt;True.while&lt;/code&gt;. That&amp;rsquo;s &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/settings-postfix-completion.html&quot;&gt;PyCharm&amp;rsquo;s Postfix completions&lt;/a&gt; working for you to help reduce backward caret jumps.&lt;/p&gt;
&lt;h2 id=&quot;running-code-in-pycharm&quot;&gt;Running Code in PyCharm&lt;/h2&gt;
&lt;p&gt;Now that you&amp;rsquo;ve coded up the game, it&amp;rsquo;s time for you to run it.&lt;/p&gt;
&lt;p&gt;You have three ways of running this program:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the shortcut &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-r&quot;&gt;R&lt;/kbd&gt;&lt;/span&gt; on Mac or &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-f10&quot;&gt;F10&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;Right-click the background and choose &lt;em&gt;Run &amp;lsquo;guess_game&amp;rsquo;&lt;/em&gt; from the menu.&lt;/li&gt;
&lt;li&gt;Since this program has the &lt;code&gt;__main__&lt;/code&gt; clause, you can click on the little green arrow to the left of the &lt;code&gt;__main__&lt;/code&gt; clause and choose &lt;em&gt;Run &amp;lsquo;guess_game&amp;rsquo;&lt;/em&gt; from there.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Use any one of the options above to run the program, and you&amp;rsquo;ll see the Run Tool pane appear at the bottom of the window, with your code output showing:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-running-script.33fb830f45b4.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/pycharm-running-script.33fb830f45b4.gif&quot; width=&quot;1068&quot; height=&quot;720&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-running-script.33fb830f45b4.gif&amp;amp;w=267&amp;amp;sig=44be962297881f8ae66557c19905a55202ee14de 267w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-running-script.33fb830f45b4.gif&amp;amp;w=534&amp;amp;sig=000552999cea7a9ce79eeec2f9db7361e9585d77 534w, https://files.realpython.com/media/pycharm-running-script.33fb830f45b4.gif 1068w&quot; sizes=&quot;75vw&quot; alt=&quot;Running a script in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Play the game for a little bit to see if you can find the number guessed. Pro tip: start with 50.   &lt;/p&gt;
&lt;h2 id=&quot;debugging-in-pycharm&quot;&gt;Debugging in PyCharm&lt;/h2&gt;
&lt;p&gt;Did you find the number? If so, you may have seen something weird after you found the number. Instead of printing the congratulations message and exiting, the program seems to start over. That&amp;rsquo;s a bug right there. To discover why the program starts over, you&amp;rsquo;ll now debug the program.&lt;/p&gt;
&lt;p&gt;First, place a breakpoint by clicking on the blank space to the left of line number 8:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-debug-breakpoint.55cf93c49859.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/pycharm-debug-breakpoint.55cf93c49859.png&quot; width=&quot;1042&quot; height=&quot;710&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-debug-breakpoint.55cf93c49859.png&amp;amp;w=260&amp;amp;sig=e714eeae34fad6c0e5889bee0f236f9c30e100a0 260w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-debug-breakpoint.55cf93c49859.png&amp;amp;w=521&amp;amp;sig=7c4692a273d49a627785a715fd0a08d4c8120649 521w, https://files.realpython.com/media/pycharm-debug-breakpoint.55cf93c49859.png 1042w&quot; sizes=&quot;75vw&quot; alt=&quot;Debug breakpoint in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This will be the point where the program will be suspended, and you can start exploring what went wrong from there on. Next, choose one of the following three ways to start debugging:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;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-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-d&quot;&gt;D&lt;/kbd&gt;&lt;/span&gt; on Mac or &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-f9&quot;&gt;F9&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;Right-click the background and choose &lt;em&gt;Debug &amp;lsquo;guess_game&amp;rsquo;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Click on the little green arrow to the left of the &lt;code&gt;__main__&lt;/code&gt; clause and choose &lt;em&gt;Debug &amp;lsquo;guess_game&lt;/em&gt; from there.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Afterwards, you&amp;rsquo;ll see a &lt;em&gt;Debug&lt;/em&gt; window open at the bottom:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-debugging-start.04246b743469.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/pycharm-debugging-start.04246b743469.png&quot; width=&quot;1043&quot; height=&quot;711&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-debugging-start.04246b743469.png&amp;amp;w=260&amp;amp;sig=cea78f8df9a7f183330e3610c90a2abeab879923 260w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-debugging-start.04246b743469.png&amp;amp;w=521&amp;amp;sig=6ae0fe4515cf7f0d52cbcda986eb9c52d0a602ee 521w, https://files.realpython.com/media/pycharm-debugging-start.04246b743469.png 1043w&quot; sizes=&quot;75vw&quot; alt=&quot;Start of debugging in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow the steps below to debug the program:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Notice that the current line is highlighted in blue.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;See that &lt;code&gt;random_int&lt;/code&gt; and its value are listed in the Debug window. Make a note of this number. (In the picture, the number is 85.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-f8&quot;&gt;F8&lt;/kbd&gt;&lt;/span&gt; to execute the current line and step &lt;em&gt;over&lt;/em&gt; to the next one. You can also use &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-f7&quot;&gt;F7&lt;/kbd&gt;&lt;/span&gt; to step &lt;em&gt;into&lt;/em&gt; the function in the current line, if necessary. As you continue executing the statements, the changes in the variables will be automatically reflected in the Debugger window.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Notice that there is the Console tab right next to the Debugger tab that opened. This Console tab and the Debugger tab are mutually exclusive. In the Console tab, you will be interacting with your program, and in the Debugger tab you will do the debugging actions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch to the Console tab to enter your guess.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Type the number shown, and then hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch back to the Debugger tab.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-f8&quot;&gt;F8&lt;/kbd&gt;&lt;/span&gt; again to evaluate the &lt;code&gt;if&lt;/code&gt; statement. Notice that you are now on line 14. But wait a minute! Why didn&amp;rsquo;t it go to the line 11? The reason is that the &lt;code&gt;if&lt;/code&gt; statement on line 10 evaluated to &lt;code&gt;False&lt;/code&gt;. But why did it evaluate to &lt;code&gt;False&lt;/code&gt; when you entered the number that was chosen?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Look carefully at line 10 and notice that we are comparing &lt;code&gt;user_guess&lt;/code&gt; with the wrong thing. Instead of comparing it with &lt;code&gt;random_int&lt;/code&gt;, we are comparing it with &lt;code&gt;randint&lt;/code&gt;, the function that was imported from the &lt;code&gt;random&lt;/code&gt; package.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change it to &lt;code&gt;random_int&lt;/code&gt;, restart the debugging, and follow the same steps again. You will see that, this time, it will go to line 11, and line 10 will evaluate to &lt;code&gt;True&lt;/code&gt;:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-debugging-scripts.bb5a077da438.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/pycharm-debugging-scripts.bb5a077da438.gif&quot; width=&quot;1092&quot; height=&quot;720&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-debugging-scripts.bb5a077da438.gif&amp;amp;w=273&amp;amp;sig=fc5de269fbc13ea5c1d8be4ca7f525e04a4bb68c 273w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-debugging-scripts.bb5a077da438.gif&amp;amp;w=546&amp;amp;sig=4719f69fd6e78ed3e68f16a9355d00d0edd85a26 546w, https://files.realpython.com/media/pycharm-debugging-scripts.bb5a077da438.gif 1092w&quot; sizes=&quot;75vw&quot; alt=&quot;Debugging Script in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Congratulations! You fixed the bug.&lt;/p&gt;
&lt;h2 id=&quot;testing-in-pycharm&quot;&gt;Testing in PyCharm&lt;/h2&gt;
&lt;p&gt;No application is reliable without unit tests. PyCharm helps you write and run them very quickly and comfortably. By default, &lt;a href=&quot;https://docs.python.org/3/library/unittest.html&quot;&gt;&lt;code&gt;unittest&lt;/code&gt;&lt;/a&gt; is used as the test runner, but PyCharm also supports other testing frameworks such as &lt;a href=&quot;http://www.pytest.org/en/latest/&quot;&gt;&lt;code&gt;pytest&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://nose.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;nose&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://docs.python.org/3/library/doctest.html&quot;&gt;&lt;code&gt;doctest&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/tox-support.html&quot;&gt;&lt;code&gt;tox&lt;/code&gt;&lt;/a&gt;, and &lt;a href=&quot;https://twistedmatrix.com/trac/wiki/TwistedTrial&quot;&gt;&lt;code&gt;trial&lt;/code&gt;&lt;/a&gt;. You can, for example, enable &lt;code&gt;pytest&lt;/code&gt; for your project like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the &lt;em&gt;Settings/Preferences → Tools → Python Integrated Tools&lt;/em&gt; settings dialog.&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;pytest&lt;/code&gt; in the Default test runner field.&lt;/li&gt;
&lt;li&gt;Click &lt;em&gt;OK&lt;/em&gt; to save the settings. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For this example, we&amp;rsquo;ll be using the default test runner &lt;code&gt;unittest&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;In the same project, create a file called &lt;code&gt;calculator.py&lt;/code&gt; and put the following &lt;code&gt;Calculator&lt;/code&gt; class in it:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Calculator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;multiply&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;a&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;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;PyCharm makes it very easy to create tests for your existing code. With the &lt;code&gt;calculator.py&lt;/code&gt; file open, execute any one of the following that you like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-t&quot;&gt;T&lt;/kbd&gt;&lt;/span&gt; on Mac or &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-t&quot;&gt;T&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;Right-click in the background of the class and then choose &lt;em&gt;Go To&lt;/em&gt; and &lt;em&gt;Test&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;On the main menu, choose &lt;em&gt;Navigate → Test&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Choose &lt;em&gt;Create New Test&amp;hellip;&lt;/em&gt;, and you will see the following window:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-create-tests.9a6cea78f9c6.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/pycharm-create-tests.9a6cea78f9c6.png&quot; width=&quot;500&quot; height=&quot;402&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-create-tests.9a6cea78f9c6.png&amp;amp;w=125&amp;amp;sig=0c50b83f35578fd8004dce9e7d55fcd3b09a1967 125w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-create-tests.9a6cea78f9c6.png&amp;amp;w=250&amp;amp;sig=f6740142e71d2d2f6196ffbe341ae09bc9a64453 250w, https://files.realpython.com/media/pycharm-create-tests.9a6cea78f9c6.png 500w&quot; sizes=&quot;75vw&quot; alt=&quot;Create tests in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Leave the defaults of &lt;em&gt;Target directory&lt;/em&gt;, &lt;em&gt;Test file name&lt;/em&gt;, and &lt;em&gt;Test class name&lt;/em&gt;. Select both of the methods and click &lt;em&gt;OK&lt;/em&gt;. Voila! PyCharm automatically created a file called &lt;code&gt;test_calculator.py&lt;/code&gt; and created the following stub tests for you in it:&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;unittest&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TestCase&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TestCalculator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fail&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_multiply&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;fail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Run the tests using one of the methods below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;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-r&quot;&gt;R&lt;/kbd&gt;&lt;/span&gt; on Mac or &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-f10&quot;&gt;F10&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;Right-click the background and choose &lt;em&gt;Run &amp;lsquo;Unittests for test_calculator.py&amp;rsquo;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Click on the little green arrow to the left of the test class name and choose &lt;em&gt;Run &amp;lsquo;Unittests for test_calculator.py&amp;rsquo;&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You&amp;rsquo;ll see the tests window open on the bottom with all the tests failing:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-failed-tests.810aa9c365cb.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/pycharm-failed-tests.810aa9c365cb.png&quot; width=&quot;972&quot; height=&quot;645&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-failed-tests.810aa9c365cb.png&amp;amp;w=243&amp;amp;sig=cb7ef285c20ed83b9771a91cc38d77342e4d3745 243w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-failed-tests.810aa9c365cb.png&amp;amp;w=486&amp;amp;sig=aaec55471da2d168048783b9c4e573f5ce876de4 486w, https://files.realpython.com/media/pycharm-failed-tests.810aa9c365cb.png 972w&quot; sizes=&quot;75vw&quot; alt=&quot;Failed tests in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice that you have the hierarchy of the test results on the left and the output of the terminal on the right. &lt;/p&gt;
&lt;p&gt;Now, implement &lt;code&gt;test_add&lt;/code&gt; by changing the code to 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;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;unittest&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TestCase&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;calculator&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Calculator&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TestCalculator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calculator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Calculator&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;assertEqual&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;calculator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;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;mi&quot;&gt;7&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;lineno&quot;&gt;10 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_multiply&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;11 &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;fail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Run the tests again, and you&amp;rsquo;ll see that one test passed and the other failed. Explore the options to show passed tests, to show ignored tests, to sort tests alphabetically, and to sort tests by duration:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-running-tests.6077562207ba.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/pycharm-running-tests.6077562207ba.gif&quot; width=&quot;1092&quot; height=&quot;720&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-running-tests.6077562207ba.gif&amp;amp;w=273&amp;amp;sig=e2238425e1cfb9a9a298741244f3021f3984dbf8 273w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-running-tests.6077562207ba.gif&amp;amp;w=546&amp;amp;sig=85203afd5ff2189fdfadad0960da514b03063953 546w, https://files.realpython.com/media/pycharm-running-tests.6077562207ba.gif 1092w&quot; sizes=&quot;75vw&quot; alt=&quot;Running tests in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the &lt;code&gt;sleep(0.1)&lt;/code&gt; method that you see in the GIF above is intentionally used to make one of the tests slower so that sorting by duration works. &lt;/p&gt;
&lt;h2 id=&quot;editing-an-existing-project-in-pycharm&quot;&gt;Editing an Existing Project in PyCharm&lt;/h2&gt;
&lt;p&gt;These single file projects are great for examples, but you&amp;rsquo;ll often work on much larger projects over a longer period of time. In this section, you&amp;rsquo;ll take a look at how PyCharm works with a larger project. &lt;/p&gt;
&lt;p&gt;To explore the project-focused features of PyCharm, you&amp;rsquo;ll use the Alcazar web framework that was built for learning purposes. To continue following along, clone the repo locally:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Clone Repo:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/optins/view/alcazar-web-framework/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-alcazar-web-framework&quot; data-focus=&quot;false&quot;&gt;Click here to clone the repo you&#39;ll use&lt;/a&gt; to explore the project-focused features of PyCharm in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;Once you have a project locally, open it in PyCharm using one of the following methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click &lt;em&gt;File → Open&lt;/em&gt; on the main menu.&lt;/li&gt;
&lt;li&gt;Click &lt;em&gt;Open&lt;/em&gt; on the &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/welcome-screen.html&quot;&gt;Welcome Screen&lt;/a&gt; if you are there.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After either of these steps, find the folder containing the project on your computer and open it.&lt;/p&gt;
&lt;p&gt;If this project contains a &lt;a href=&quot;https://realpython.com/python-virtual-environments-a-primer/&quot;&gt;virtual environment&lt;/a&gt;, then PyCharm will automatically use this virtual environment and make it the project interpreter.&lt;/p&gt;
&lt;p&gt;If you need to configure a different &lt;code&gt;virtualenv&lt;/code&gt;, then open &lt;em&gt;Preferences&lt;/em&gt; on Mac by pressing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-comma&quot;&gt;,&lt;/kbd&gt;&lt;/span&gt; or &lt;em&gt;Settings&lt;/em&gt; on Windows or Linux by 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-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-s&quot;&gt;S&lt;/kbd&gt;&lt;/span&gt; and find the &lt;em&gt;Project: ProjectName&lt;/em&gt; section. Open the drop-down and choose &lt;em&gt;Project Interpreter&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-project-interpreter.57282306555a.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/pycharm-project-interpreter.57282306555a.png&quot; width=&quot;1083&quot; height=&quot;723&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-project-interpreter.57282306555a.png&amp;amp;w=270&amp;amp;sig=286643bc473f648bbcce27338c980eb023746ac2 270w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-project-interpreter.57282306555a.png&amp;amp;w=541&amp;amp;sig=6d33c5adf0380e8c5b01ae9430436983580b4b49 541w, https://files.realpython.com/media/pycharm-project-interpreter.57282306555a.png 1083w&quot; sizes=&quot;75vw&quot; alt=&quot;Project interpreter in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Choose the &lt;code&gt;virtualenv&lt;/code&gt; from the drop-down list. If it&amp;rsquo;s not there, then click on the settings button to the right of the drop-down list and then choose &lt;em&gt;Add&amp;hellip;&lt;/em&gt;. The rest of the steps should be the same as when we were &lt;a href=&quot;#writing-code-in-pycharm&quot;&gt;creating a new project&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;searching-and-navigating-in-pycharm&quot;&gt;Searching and Navigating in PyCharm&lt;/h2&gt;
&lt;p&gt;In a big project where it&amp;rsquo;s difficult for a single person to remember where everything is located, it&amp;rsquo;s very important to be able to quickly navigate and find what you looking for. PyCharm has you covered here as well. Use the project you opened in the section above to practice these shortcuts: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Searching for a fragment in the current file:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-f&quot;&gt;F&lt;/kbd&gt;&lt;/span&gt; on Mac or &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; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Searching for a fragment in the entire project:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&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-f&quot;&gt;F&lt;/kbd&gt;&lt;/span&gt; on Mac or &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-f&quot;&gt;F&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Searching for a class:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-o&quot;&gt;O&lt;/kbd&gt;&lt;/span&gt; on Mac or &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-n&quot;&gt;N&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Searching for a file:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&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-o&quot;&gt;O&lt;/kbd&gt;&lt;/span&gt; on Mac or &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-n&quot;&gt;N&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Searching all if you don&amp;rsquo;t know whether it&amp;rsquo;s a file, class, or a code fragment that you are looking for:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;/span&gt; twice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As for the navigation, the following shortcuts may save you a lot of time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Going to the declaration of a variable:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;/span&gt; on Mac or &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux, and click on the variable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Finding usages of a class, a method, or any symbol:&lt;/strong&gt; Press &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-f7&quot;&gt;F7&lt;/kbd&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seeing your recent changes:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&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 go to &lt;em&gt;View → Recent Changes&lt;/em&gt; on the main menu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seeing your recent files:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-e&quot;&gt;E&lt;/kbd&gt;&lt;/span&gt; on Mac or &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-e&quot;&gt;E&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux, or go to &lt;em&gt;View → Recent Files&lt;/em&gt; on the main menu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Going backward and forward through your history of navigation after you jumped around:&lt;/strong&gt; Press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-bracket-left&quot;&gt;[&lt;/kbd&gt;&lt;/span&gt; / &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-bracket-right&quot;&gt;]&lt;/kbd&gt;&lt;/span&gt; on Mac or &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-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-arrow-left&quot;&gt;Left&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-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-arrow-right&quot;&gt;Right&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more details, see the &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/tutorial-exploring-navigation-and-search.html&quot;&gt;official documentation&lt;/a&gt;. &lt;/p&gt;
&lt;h2 id=&quot;using-version-control-in-pycharm&quot;&gt;Using Version Control in PyCharm&lt;/h2&gt;
&lt;p&gt;Version control systems such as &lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt; and &lt;a href=&quot;https://www.mercurial-scm.org/&quot;&gt;Mercurial&lt;/a&gt; are some of the most important tools in the modern software development world. So, it is essential for an IDE to support them. PyCharm does that very well by integrating with a lot of popular VC systems such as Git (and &lt;a href=&quot;https://github.com/&quot;&gt;Github&lt;/a&gt;), Mercurial, &lt;a href=&quot;https://www.perforce.com/solutions/version-control&quot;&gt;Perforce&lt;/a&gt; and, &lt;a href=&quot;https://subversion.apache.org/&quot;&gt;Subversion&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;a href=&quot;https://realpython.com/python-git-github-intro/&quot;&gt;Git&lt;/a&gt; is used for the following examples.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;configuring-vcs&quot;&gt;Configuring VCS&lt;/h3&gt;
&lt;p&gt;To enable VCS integration. Go to &lt;em&gt;VCS → VCS Operations Popup&amp;hellip;&lt;/em&gt; from the menu on the top or 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-v&quot;&gt;V&lt;/kbd&gt;&lt;/span&gt; on Mac 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-grave&quot;&gt;`&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux. Choose &lt;em&gt;Enable Version Control Integration&amp;hellip;&lt;/em&gt;. You&amp;rsquo;ll see the following window open:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-enable-vc-integration.b30ec94c1246.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/pycharm-enable-vc-integration.b30ec94c1246.png&quot; width=&quot;715&quot; height=&quot;147&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-enable-vc-integration.b30ec94c1246.png&amp;amp;w=178&amp;amp;sig=7ef55e4ed6068c86d831adaefc1af11f4c083763 178w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-enable-vc-integration.b30ec94c1246.png&amp;amp;w=357&amp;amp;sig=c701d809b49e9837477c14e8dfe34dc4cfa66c33 357w, https://files.realpython.com/media/pycharm-enable-vc-integration.b30ec94c1246.png 715w&quot; sizes=&quot;75vw&quot; alt=&quot;Enable Version Control Integration in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Choose &lt;em&gt;Git&lt;/em&gt; from the drop down list, click &lt;em&gt;OK&lt;/em&gt;, and you have VCS enabled for your project. Note that if you opened an existing project that has version control enabled, then PyCharm will see that and automatically enable it.&lt;/p&gt;
&lt;p&gt;Now, if you go to the &lt;em&gt;VCS Operations Popup&amp;hellip;&lt;/em&gt;, you&amp;rsquo;ll see a different popup with the options to do &lt;code&gt;git add&lt;/code&gt;, &lt;code&gt;git stash&lt;/code&gt;, &lt;code&gt;git branch&lt;/code&gt;, &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;git push&lt;/code&gt; and more:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-vcs-operations.70dbafcb983a.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-50&quot; src=&quot;https://files.realpython.com/media/pycharm-vcs-operations.70dbafcb983a.png&quot; width=&quot;392&quot; height=&quot;379&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-vcs-operations.70dbafcb983a.png&amp;amp;w=98&amp;amp;sig=f285b015c957936448441c4ec8b03cf8627cdffc 98w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-vcs-operations.70dbafcb983a.png&amp;amp;w=196&amp;amp;sig=a16c449a21dde2a2b0f2f7533c92e71574cd3d60 196w, https://files.realpython.com/media/pycharm-vcs-operations.70dbafcb983a.png 392w&quot; sizes=&quot;75vw&quot; alt=&quot;VCS operations in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you can&amp;rsquo;t find what you need, you can most probably find it by going to &lt;em&gt;VCS&lt;/em&gt; from the top menu and choosing &lt;em&gt;Git&lt;/em&gt;, where you can even create and view pull requests.&lt;/p&gt;
&lt;h3 id=&quot;committing-and-conflict-resolution&quot;&gt;Committing and Conflict Resolution&lt;/h3&gt;
&lt;p&gt;These are two features of VCS integration in PyCharm that I personally use and enjoy a lot! Let&amp;rsquo;s say you have finished your work and want to commit it. Go to &lt;em&gt;VCS → VCS Operations Popup&amp;hellip; → Commit&amp;hellip;&lt;/em&gt; or press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-k&quot;&gt;K&lt;/kbd&gt;&lt;/span&gt; on Mac or &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-k&quot;&gt;K&lt;/kbd&gt;&lt;/span&gt; on Windows or Linux. You&amp;rsquo;ll see the following window open:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-commit-window.a4ceff16c2d3.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/pycharm-commit-window.a4ceff16c2d3.png&quot; width=&quot;929&quot; height=&quot;682&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-commit-window.a4ceff16c2d3.png&amp;amp;w=232&amp;amp;sig=935dabf7a28cf757a5c87165e3da494540c3e4a6 232w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-commit-window.a4ceff16c2d3.png&amp;amp;w=464&amp;amp;sig=7a05fe8a5cbfb1c3524c24515f9a8d7fa3211591 464w, https://files.realpython.com/media/pycharm-commit-window.a4ceff16c2d3.png 929w&quot; sizes=&quot;75vw&quot; alt=&quot;Commit window in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this window, you can do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Choose which files to commit&lt;/li&gt;
&lt;li&gt;Write your commit message&lt;/li&gt;
&lt;li&gt;Do all kinds of checks and cleanup &lt;a href=&quot;https://www.jetbrains.com/help/idea/commit-changes-dialog.html#before_commit&quot;&gt;before commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;See the difference of changes&lt;/li&gt;
&lt;li&gt;Commit and push at once by pressing the arrow to the right of the &lt;em&gt;Commit&lt;/em&gt; button on the right bottom and choosing &lt;em&gt;Commit and Push&amp;hellip;&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It can feel magical and fast, especially if you&amp;rsquo;re used to doing everything manually on the command line.&lt;/p&gt;
&lt;p&gt;When you work in a team, &lt;strong&gt;merge conflicts&lt;/strong&gt; do happen. When somebody commits changes to a file that you&amp;rsquo;re working on, but their changes overlap with yours because both of you changed the same lines, then VCS will not be able to figure out if it should choose your changes or those of your teammate. So you&amp;rsquo;ll get these unfortunate arrows and symbols:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-conflicts.74b23b9ec798.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/pycharm-conflicts.74b23b9ec798.png&quot; width=&quot;996&quot; height=&quot;691&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-conflicts.74b23b9ec798.png&amp;amp;w=249&amp;amp;sig=d02221be0ce12dbc9a8ea7514e047bb608b16c08 249w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-conflicts.74b23b9ec798.png&amp;amp;w=498&amp;amp;sig=1286c7aa0f62795e01c6a2f0607096b8c0d67b20 498w, https://files.realpython.com/media/pycharm-conflicts.74b23b9ec798.png 996w&quot; sizes=&quot;75vw&quot; alt=&quot;Conflicts in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This looks strange, and it&amp;rsquo;s difficult to figure out which changes should be deleted and which ones should stay. PyCharm to the rescue! It has a much nicer and cleaner way of resolving conflicts. Go to &lt;em&gt;VCS&lt;/em&gt; in the top menu, choose &lt;em&gt;Git&lt;/em&gt; and then &lt;em&gt;Resolve conflicts&amp;hellip;&lt;/em&gt;. Choose the file whose conflicts you want to resolve and click on &lt;em&gt;Merge&lt;/em&gt;. You will see the following window open:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-conflict-resolving-window.eea8f79a12b2.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/pycharm-conflict-resolving-window.eea8f79a12b2.png&quot; width=&quot;1174&quot; height=&quot;709&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-conflict-resolving-window.eea8f79a12b2.png&amp;amp;w=293&amp;amp;sig=ef195e8acbb5ec9fa55fca46a43486995c2efca7 293w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-conflict-resolving-window.eea8f79a12b2.png&amp;amp;w=587&amp;amp;sig=067731ba579736c92c747eb128b3fb02b0d68417 587w, https://files.realpython.com/media/pycharm-conflict-resolving-window.eea8f79a12b2.png 1174w&quot; sizes=&quot;75vw&quot; alt=&quot;Conflict resolving windown in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On the left column, you will see your changes. On the right one, the changes made by your teammate. Finally, in the middle column, you will see the result. The conflicting lines are highlighted, and you can see a little &lt;em&gt;X&lt;/em&gt; and &lt;em&gt;&amp;gt;&amp;gt;&lt;/em&gt;/&lt;em&gt;&amp;lt;&amp;lt;&lt;/em&gt; right beside those lines. Press the arrows to accept the changes and the &lt;em&gt;X&lt;/em&gt; to decline. After you resolve all those conflicts, click the &lt;em&gt;Apply&lt;/em&gt; button: &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-resolving-conflicts.d3128ce78c45.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/pycharm-resolving-conflicts.d3128ce78c45.gif&quot; width=&quot;1200&quot; height=&quot;720&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-resolving-conflicts.d3128ce78c45.gif&amp;amp;w=300&amp;amp;sig=099dcca659431f9d2a1315b1fea5d7cbe246425c 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-resolving-conflicts.d3128ce78c45.gif&amp;amp;w=600&amp;amp;sig=6b98751300d8750c93d80cf7b65e96fb57d81714 600w, https://files.realpython.com/media/pycharm-resolving-conflicts.d3128ce78c45.gif 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Resolving Conflicts in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the GIF above, for the first conflicting line, the author declined his own changes and accepted those of his teammates. Conversely, the author accepted his own changes and declined his teammates&amp;rsquo; for the second conflicting line.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a lot more that you can do with the VCS integration in PyCharm. For more details, see &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/version-control-integration.html&quot;&gt;this documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;using-plugins-and-external-tools-in-pycharm&quot;&gt;Using Plugins and External Tools in PyCharm&lt;/h2&gt;
&lt;p&gt;You can find almost everything you need for development in PyCharm. If you can&amp;rsquo;t, there is most probably a &lt;a href=&quot;https://plugins.jetbrains.com/&quot;&gt;plugin&lt;/a&gt; that adds that functionality you need to PyCharm. For example, they can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add support for various languages and frameworks &lt;/li&gt;
&lt;li&gt;Boost your productivity with shortcut hints, file watchers, and so on &lt;/li&gt;
&lt;li&gt;Help you learn a new programming language with coding exercises&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For instance, &lt;a href=&quot;https://plugins.jetbrains.com/plugin/164-ideavim&quot;&gt;IdeaVim&lt;/a&gt; adds Vim emulation to PyCharm. If you like Vim, this can be a pretty good combination. &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://plugins.jetbrains.com/plugin/8006-material-theme-ui&quot;&gt;Material Theme UI&lt;/a&gt; changes the appearance of PyCharm to a Material Design look and feel: &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-material-theme.178175815adc.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/pycharm-material-theme.178175815adc.png&quot; width=&quot;1110&quot; height=&quot;743&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-material-theme.178175815adc.png&amp;amp;w=277&amp;amp;sig=60ec4c8b5f6a89af345a230518e21ee8a33d174b 277w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-material-theme.178175815adc.png&amp;amp;w=555&amp;amp;sig=fdac8603145ed77eb443abcbbe8ebdb9811bdff4 555w, https://files.realpython.com/media/pycharm-material-theme.178175815adc.png 1110w&quot; sizes=&quot;75vw&quot; alt=&quot;Material Theme in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://plugins.jetbrains.com/plugin/9442-vue-js&quot;&gt;Vue.js&lt;/a&gt; adds support for &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue.js&lt;/a&gt; projects. &lt;a href=&quot;https://plugins.jetbrains.com/plugin/7793-markdown&quot;&gt;Markdown&lt;/a&gt; provides the capability to edit Markdown files within the IDE and see the rendered HTML in a live preview. You can find and install all of the available plugins by going to the &lt;em&gt;Preferences → Plugins&lt;/em&gt; on Mac or &lt;em&gt;Settings → Plugins&lt;/em&gt; on Windows or Linux, under the &lt;em&gt;Marketplace&lt;/em&gt; tab:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-plugin-marketplace.7d1cecfdc8b3.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/pycharm-plugin-marketplace.7d1cecfdc8b3.png&quot; width=&quot;1047&quot; height=&quot;687&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-plugin-marketplace.7d1cecfdc8b3.png&amp;amp;w=261&amp;amp;sig=8d4a9ba35b5eb27b5604f86108b79f28e40f3cc9 261w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-plugin-marketplace.7d1cecfdc8b3.png&amp;amp;w=523&amp;amp;sig=ec5e20ae96bf9ee37a1011bcc2203e7d1599b4a4 523w, https://files.realpython.com/media/pycharm-plugin-marketplace.7d1cecfdc8b3.png 1047w&quot; sizes=&quot;75vw&quot; alt=&quot;Plugin Marketplace in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you can&amp;rsquo;t find what you need, you can even &lt;a href=&quot;http://www.jetbrains.org/intellij/sdk/docs/basics.html&quot;&gt;develop your own plugin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you can&amp;rsquo;t find the right plugin and don&amp;rsquo;t want to develop your own because there&amp;rsquo;s already a package in PyPI, then you can add it to PyCharm as an external tool. Take &lt;a href=&quot;http://flake8.pycqa.org/en/latest/&quot;&gt;&lt;code&gt;Flake8&lt;/code&gt;&lt;/a&gt;, the code analyzer, as an example. &lt;/p&gt;
&lt;p&gt;First, install &lt;code&gt;flake8&lt;/code&gt; in your virtualenv with &lt;code&gt;pip install flake8&lt;/code&gt; in the Terminal app of your choice. You can also use the one integrated into PyCharm:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-terminal.bb20cae6697e.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/pycharm-terminal.bb20cae6697e.png&quot; width=&quot;972&quot; height=&quot;646&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-terminal.bb20cae6697e.png&amp;amp;w=243&amp;amp;sig=860217f31e60a4bb574e169ee05b6788cacaa388 243w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-terminal.bb20cae6697e.png&amp;amp;w=486&amp;amp;sig=26a30f328e42cc19e7e652c44767093480dbf352 486w, https://files.realpython.com/media/pycharm-terminal.bb20cae6697e.png 972w&quot; sizes=&quot;75vw&quot; alt=&quot;Terminal in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then, go to &lt;em&gt;Preferences → Tools&lt;/em&gt; on Mac or &lt;em&gt;Settings → Tools&lt;/em&gt; on Windows/Linux, and then choose &lt;em&gt;External Tools&lt;/em&gt;. Then click on the little &lt;em&gt;+&lt;/em&gt; button at the bottom (1). In the new popup window, insert the details as shown below and click &lt;em&gt;OK&lt;/em&gt; for both windows:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-flake8-tool.3963506224b4.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/pycharm-flake8-tool.3963506224b4.png&quot; width=&quot;1082&quot; height=&quot;720&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-flake8-tool.3963506224b4.png&amp;amp;w=270&amp;amp;sig=152f2ccf0a75a950b6a5cd6b5087507b66288595 270w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-flake8-tool.3963506224b4.png&amp;amp;w=541&amp;amp;sig=ee7221ee226076dfeaedfd5d2756263e351d8d14 541w, https://files.realpython.com/media/pycharm-flake8-tool.3963506224b4.png 1082w&quot; sizes=&quot;75vw&quot; alt=&quot;Flake8 tool in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here, &lt;em&gt;Program&lt;/em&gt; (2) refers to the Flake8 executable that can be found in the folder &lt;em&gt;/bin&lt;/em&gt; of your virtual environment. &lt;em&gt;Arguments&lt;/em&gt; (3) refers to which file you want to analyze with the help of Flake8. &lt;em&gt;Working directory&lt;/em&gt; is the directory of your project.&lt;/p&gt;
&lt;p&gt;You could hardcode the absolute paths for everything here, but that would mean that you couldn&amp;rsquo;t use this external tool in other projects. You would be able to use it only inside one project for one file. &lt;/p&gt;
&lt;p&gt;So you need to use something called &lt;em&gt;Macros&lt;/em&gt;. Macros are basically variables in the format of &lt;code&gt;$name$&lt;/code&gt; that change according to your context. For example, &lt;code&gt;$FileName$&lt;/code&gt; is &lt;code&gt;first.py&lt;/code&gt; when you&amp;rsquo;re editing &lt;code&gt;first.py&lt;/code&gt;, and it is &lt;code&gt;second.py&lt;/code&gt; when you&amp;rsquo;re editing &lt;code&gt;second.py&lt;/code&gt;. You can see their list and insert any of them by clicking on the &lt;em&gt;Insert Macro&amp;hellip;&lt;/em&gt; buttons. Because you used macros here, the values will change according to the project you&amp;rsquo;re currently working on, and Flake8 will continue to do its job properly.   &lt;/p&gt;
&lt;p&gt;In order to use it, create a file &lt;code&gt;example.py&lt;/code&gt; and put the following code in it:&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;CONSTANT_VAR&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;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It deliberately breaks some of the Flake8 rules. Right-click the background of this file. Choose &lt;em&gt;External Tools&lt;/em&gt; and then &lt;em&gt;Flake8&lt;/em&gt;. Voilà! The output of the Flake8 analysis will appear at the bottom: &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-flake8-output.5b78e911e6d3.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/pycharm-flake8-output.5b78e911e6d3.png&quot; width=&quot;997&quot; height=&quot;634&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-flake8-output.5b78e911e6d3.png&amp;amp;w=249&amp;amp;sig=8fecbaaf9d4e2daa2bbe443be4b6dee2634f2a46 249w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-flake8-output.5b78e911e6d3.png&amp;amp;w=498&amp;amp;sig=4e41c6dbac28fbe23c18716f49c3cadf63767500 498w, https://files.realpython.com/media/pycharm-flake8-output.5b78e911e6d3.png 997w&quot; sizes=&quot;75vw&quot; alt=&quot;Flake8 Output in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In order to make it even better, you can add a shortcut for it. Go to &lt;em&gt;Preferences&lt;/em&gt; on Mac or to &lt;em&gt;Settings&lt;/em&gt; on Windows or Linux. Then, go to &lt;em&gt;Keymap → External Tools → External Tools&lt;/em&gt;. Double-click &lt;em&gt;Flake8&lt;/em&gt; and choose &lt;em&gt;Add Keyboard Shortcut&lt;/em&gt;. You&amp;rsquo;ll see this window:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-add-shortcut.8c66b2bd12c0.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/pycharm-add-shortcut.8c66b2bd12c0.png&quot; width=&quot;1084&quot; height=&quot;724&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-add-shortcut.8c66b2bd12c0.png&amp;amp;w=271&amp;amp;sig=e95cc32634af125588e6881ec6992dace79ec667 271w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-add-shortcut.8c66b2bd12c0.png&amp;amp;w=542&amp;amp;sig=836cbeec5256df8e8048aa6a0c3e7d89b2bac444 542w, https://files.realpython.com/media/pycharm-add-shortcut.8c66b2bd12c0.png 1084w&quot; sizes=&quot;75vw&quot; alt=&quot;Add shortcut in PyCharm&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the image above, the shortcut is &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-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-a&quot;&gt;A&lt;/kbd&gt;&lt;/span&gt; for this tool. Add your preferred shortcut in the textbox and click &lt;em&gt;OK&lt;/em&gt; for both windows. Now you can now use that shortcut to analyze the file you&amp;rsquo;re currently working on with Flake8.&lt;/p&gt;
&lt;h2 id=&quot;pycharm-professional-features&quot;&gt;PyCharm Professional Features&lt;/h2&gt;
&lt;p&gt;PyCharm Professional is a paid version of PyCharm with more out-of-the-box features and integrations. In this section, you&amp;rsquo;ll mainly be presented with overviews of its main features and links to the official documentation, where each feature is discussed in detail. Remember that none of the following features is available in the Community edition. &lt;/p&gt;
&lt;h3 id=&quot;django-support&quot;&gt;Django Support&lt;/h3&gt;
&lt;p&gt;PyCharm has extensive support for &lt;a href=&quot;https://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt;, one of the most popular and beloved &lt;a href=&quot;https://realpython.com/learning-paths/become-python-web-developer/&quot;&gt;Python web frameworks&lt;/a&gt;. To make sure that it&amp;rsquo;s enabled, do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;em&gt;Preferences&lt;/em&gt; on Mac or &lt;em&gt;Settings&lt;/em&gt; on Windows or Linux.&lt;/li&gt;
&lt;li&gt;Choose &lt;em&gt;Languages and Frameworks&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Choose &lt;em&gt;Django&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Check the checkbox &lt;em&gt;Enable Django support&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Apply changes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now that you&amp;rsquo;ve enabled Django support, your Django development journey will be a lot easier in PyCharm:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When creating a project, you&amp;rsquo;ll have a dedicated Django project type. This means that, when you choose this type, you&amp;rsquo;ll have all the necessary files and settings. This is the equivalent of using &lt;code&gt;django-admin startproject mysite&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can run &lt;code&gt;manage.py&lt;/code&gt; commands directly inside PyCharm. &lt;/li&gt;
&lt;li&gt;Django templates are supported, including:&lt;ul&gt;
&lt;li&gt;Syntax and error highlighting&lt;/li&gt;
&lt;li&gt;Code completion&lt;/li&gt;
&lt;li&gt;Navigation&lt;/li&gt;
&lt;li&gt;Completion for block names&lt;/li&gt;
&lt;li&gt;Completion for custom tags and filters&lt;/li&gt;
&lt;li&gt;Quick documentation for tags and filters&lt;/li&gt;
&lt;li&gt;Capability to debug them&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Code completion in all other Django parts such as views, URLs and models, and code insight support for Django ORM.&lt;/li&gt;
&lt;li&gt;Model dependency diagrams for Django models.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more details on Django support, see the &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/django-support7.html&quot;&gt;official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;database-support&quot;&gt;Database Support&lt;/h3&gt;
&lt;p&gt;Modern database development is a complex task with many supporting systems and workflows. That&amp;rsquo;s why JetBrains, the company behind PyCharm, developed a standalone IDE called &lt;a href=&quot;https://www.jetbrains.com/datagrip/&quot;&gt;DataGrip&lt;/a&gt; for that. It&amp;rsquo;s a separate product from PyCharm with a separate license. &lt;/p&gt;
&lt;p&gt;Luckily, PyCharm supports all the features that are available in DataGrip through a plugin called &lt;em&gt;Database tools and SQL&lt;/em&gt;, which is enabled by default. With the help of it, you can query, create and manage databases whether they&amp;rsquo;re working locally, on a server, or in the cloud. The plugin supports MySQL, PostgreSQL, Microsoft SQL Server, SQLite, MariaDB, Oracle, Apache Cassandra, and others. For more information on what you can do with this plugin, check out &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/relational-databases.html&quot;&gt;the comprehensive documentation on the database support&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;thread-concurrency-visualization&quot;&gt;Thread Concurrency Visualization&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://channels.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;Django Channels&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://realpython.com/async-io-python/&quot;&gt;&lt;code&gt;asyncio&lt;/code&gt;&lt;/a&gt;, and the recent frameworks like &lt;a href=&quot;https://www.starlette.io/&quot;&gt;&lt;code&gt;Starlette&lt;/code&gt;&lt;/a&gt; are examples of a growing trend in asynchronous Python programming. While it&amp;rsquo;s true that asynchronous programs do bring a lot of benefits to the table, it&amp;rsquo;s also notoriously hard to write and debug them. In such cases, &lt;em&gt;Thread Concurrency Visualization&lt;/em&gt; can be just what the doctor ordered because it helps you take full control over your multi-threaded applications and optimize them.&lt;/p&gt;
&lt;p&gt;Check out &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/thread-concurrency-visualization.html&quot;&gt;the comprehensive documentation of this feature&lt;/a&gt; for more details.&lt;/p&gt;
&lt;h3 id=&quot;profiler&quot;&gt;Profiler&lt;/h3&gt;
&lt;p&gt;Speaking of optimization, profiling is another technique that you can use to optimize your code. With its help, you can see which parts of your code are taking most of the execution time. A profiler runs in the following order of priority: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://vmprof.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;vmprof&lt;/code&gt;&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sumerc/yappi&quot;&gt;&lt;code&gt;yappi&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/profile.html&quot;&gt;&lt;code&gt;cProfile&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you don&amp;rsquo;t have &lt;code&gt;vmprof&lt;/code&gt; or &lt;code&gt;yappi&lt;/code&gt; installed, then it&amp;rsquo;ll fall back to the standard &lt;code&gt;cProfile&lt;/code&gt;. It&amp;rsquo;s &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/profiler.html&quot;&gt;well-documented&lt;/a&gt;, so I won&amp;rsquo;t rehash it here. &lt;/p&gt;
&lt;h3 id=&quot;scientific-mode&quot;&gt;Scientific Mode&lt;/h3&gt;
&lt;p&gt;Python is not only a language for general and web programming. It also emerged as the best tool for data science and machine learning over these last years thanks to libraries and tools like &lt;a href=&quot;http://www.numpy.org/&quot;&gt;NumPy&lt;/a&gt;, &lt;a href=&quot;https://www.scipy.org/&quot;&gt;SciPy&lt;/a&gt;, &lt;a href=&quot;https://scikit-learn.org/&quot;&gt;scikit-learn&lt;/a&gt;, &lt;a href=&quot;https://matplotlib.org/&quot;&gt;Matplotlib&lt;/a&gt;, &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter&lt;/a&gt;, and more. With such powerful libraries available, you need a powerful IDE to support all the functions such as graphing and analyzing those libraries have. PyCharm provides everything you need as &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/matplotlib-support.html&quot;&gt;thoroughly documented here&lt;/a&gt;.  &lt;/p&gt;
&lt;h3 id=&quot;remote-development&quot;&gt;Remote Development&lt;/h3&gt;
&lt;p&gt;One common cause of bugs in many applications is that development and production environments differ. Although, in most cases, it&amp;rsquo;s not possible to provide an exact copy of the production environment for development, pursuing it is a worthy goal.&lt;/p&gt;
&lt;p&gt;With PyCharm, you can debug your application using an interpreter that is located on the other computer, such as a Linux VM. As a result, you can have the same interpreter as your production environment to fix and avoid many bugs resulting from the difference between development and production environments. Make sure to check out the &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html&quot;&gt;official documentation&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;PyCharm is one of best, if not the best, full-featured, dedicated, and versatile IDEs for Python development. It offers a ton of benefits, saving you a lot of time by helping you with routine tasks. Now you know how to be productive with it!&lt;/p&gt;
&lt;p&gt;In this article, you learned about a lot, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Installing PyCharm&lt;/li&gt;
&lt;li&gt;Writing code in PyCharm&lt;/li&gt;
&lt;li&gt;Running your code in PyCharm&lt;/li&gt;
&lt;li&gt;Debugging and testing your code in PyCharm&lt;/li&gt;
&lt;li&gt;Editing an existing project in PyCharm&lt;/li&gt;
&lt;li&gt;Searching and navigating in PyCharm&lt;/li&gt;
&lt;li&gt;Using Version Control in PyCharm&lt;/li&gt;
&lt;li&gt;Using Plugins and External Tools in PyCharm&lt;/li&gt;
&lt;li&gt;Using PyCharm Professional features, such as Django support and Scientific mode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If there&amp;rsquo;s anything you&amp;rsquo;d like to ask or share, please reach out in the comments below. There&amp;rsquo;s also a lot more information at the &lt;a href=&quot;https://www.jetbrains.com/pycharm/documentation/&quot;&gt;PyCharm website&lt;/a&gt; for you to explore.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Clone Repo:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/optins/view/alcazar-web-framework/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-alcazar-web-framework&quot; data-focus=&quot;false&quot;&gt;Click here to clone the repo you&#39;ll use&lt;/a&gt; to explore the project-focused features of PyCharm in this tutorial.&lt;/p&gt;&lt;/div&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>How to Use Python Lambda Functions</title>
      <id>https://realpython.com/courses/python-lambda-functions/</id>
      <link href="https://realpython.com/courses/python-lambda-functions/"/>
      <updated>2019-08-27T14:00:00+00:00</updated>
      <summary>In this step-by-step course, you&#39;ll learn about Python lambda functions. You&#39;ll see how they compare with regular functions and how you can use them in accordance with best practices.</summary>
      <content type="html">
        &lt;p&gt;Python and other languages like Java, C#, and even C++ have had lambda functions added to their syntax, whereas languages like LISP or the ML family of languages, Haskell, OCaml, and F#, use lambdas as a core concept. Python lambdas are little, anonymous functions, subject to a more restrictive but more concise syntax than regular Python functions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this course, you&amp;rsquo;ll know:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How Python lambdas came to be &lt;/li&gt;
&lt;li&gt;How lambdas compare with regular function objects&lt;/li&gt;
&lt;li&gt;How to write lambda functions&lt;/li&gt;
&lt;li&gt;Which functions in the Python standard library leverage lambdas&lt;/li&gt;
&lt;li&gt;When to use or avoid Python lambda functions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This course is mainly for intermediate to experienced Python programmers, but it is accessible to any curious minds with interest in programming. All the examples included in this tutorial have been tested with Python 3.7.&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>A Guide to Excel Spreadsheets in Python With openpyxl</title>
      <id>https://realpython.com/openpyxl-excel-spreadsheets-python/</id>
      <link href="https://realpython.com/openpyxl-excel-spreadsheets-python/"/>
      <updated>2019-08-26T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how to handle spreadsheets in Python using the openpyxl package. You&#39;ll learn how to manipulate Excel spreadsheets, extract information from spreadsheets, create simple or more complex spreadsheets, including adding styles, charts, and so on.</summary>
      <content type="html">
        &lt;p&gt;Excel spreadsheets are one of those things you might have to deal with at some point. Either it&amp;rsquo;s because your boss loves them or because marketing needs them, you might have to learn how to work with spreadsheets, and that&amp;rsquo;s when knowing &lt;code&gt;openpyxl&lt;/code&gt; comes in handy!&lt;/p&gt;
&lt;p&gt;Spreadsheets are a very intuitive and user-friendly way to manipulate large datasets without any prior technical background. That&amp;rsquo;s why they&amp;rsquo;re still so commonly used today.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this article, you&amp;rsquo;ll learn how to use openpyxl to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manipulate Excel spreadsheets with confidence&lt;/li&gt;
&lt;li&gt;Extract information from spreadsheets&lt;/li&gt;
&lt;li&gt;Create simple or more complex spreadsheets, including adding styles, charts, and so on&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article is written for intermediate developers who have a pretty good knowledge of Python data structures, such as &lt;a href=&quot;https://realpython.com/python-dicts/&quot;&gt;dicts&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;lists&lt;/a&gt;, but also feel comfortable around &lt;a href=&quot;https://realpython.com/python3-object-oriented-programming/&quot;&gt;OOP&lt;/a&gt; and more intermediate level topics.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Dataset:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/optins/view/openpyxl-sample-dataset/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-openpyxl-sample-dataset&quot; data-focus=&quot;false&quot;&gt;Click here to download the dataset for the openpyxl exercise you&#39;ll be following in this tutorial.&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;before-you-begin&quot;&gt;Before You Begin&lt;/h2&gt;
&lt;p&gt;If you ever get asked to extract some data from a database or log file into an Excel spreadsheet, or if you often have to convert an Excel spreadsheet into some more usable programmatic form, then this tutorial is perfect for you. Let&amp;rsquo;s jump into the &lt;code&gt;openpyxl&lt;/code&gt; caravan!&lt;/p&gt;
&lt;h3 id=&quot;practical-use-cases&quot;&gt;Practical Use Cases&lt;/h3&gt;
&lt;p&gt;First things first, when would you need to use a package like &lt;code&gt;openpyxl&lt;/code&gt; in a real-world scenario? You&amp;rsquo;ll see a few examples below, but really, there are hundreds of possible scenarios where this knowledge could come in handy.&lt;/p&gt;
&lt;h4 id=&quot;importing-new-products-into-a-database&quot;&gt;Importing New Products Into a Database&lt;/h4&gt;
&lt;p&gt;You are responsible for tech in an online store company, and your boss doesn&amp;rsquo;t want to pay for a cool and expensive CMS system.&lt;/p&gt;
&lt;p&gt;Every time they want to add new products to the online store, they come to you with an Excel spreadsheet with a few hundred rows and, for each of them, you have the product name, description, price, and so forth.&lt;/p&gt;
&lt;p&gt;Now, to import the data, you&amp;rsquo;ll have to iterate over each spreadsheet row and add each product to the online store.&lt;/p&gt;
&lt;h4 id=&quot;exporting-database-data-into-a-spreadsheet&quot;&gt;Exporting Database Data Into a Spreadsheet&lt;/h4&gt;
&lt;p&gt;Say you have a Database table where you record all your users&amp;rsquo; information, including name, phone number, email address, and so forth.&lt;/p&gt;
&lt;p&gt;Now, the Marketing team wants to contact all users to give them some discounted offer or promotion. However, they don&amp;rsquo;t have access to the Database, or they don&amp;rsquo;t know how to use SQL to extract that information easily.&lt;/p&gt;
&lt;p&gt;What can you do to help? Well, you can make a quick script using &lt;code&gt;openpyxl&lt;/code&gt; that iterates over every single User record and puts all the essential information into an Excel spreadsheet.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s gonna earn you an extra slice of cake at your company&amp;rsquo;s next birthday party!&lt;/p&gt;
&lt;h4 id=&quot;appending-information-to-an-existing-spreadsheet&quot;&gt;Appending Information to an Existing Spreadsheet&lt;/h4&gt;
&lt;p&gt;You may also have to open a spreadsheet, read the information in it and, according to some business logic, append more data to it.&lt;/p&gt;
&lt;p&gt;For example, using the online store scenario again, say you get an Excel spreadsheet with a list of users and you need to append to each row the total amount they&amp;rsquo;ve spent in your store.&lt;/p&gt;
&lt;p&gt;This data is in the Database and, in order to do this, you have to read the spreadsheet, iterate through each row, fetch the total amount spent from the Database and then write back to the spreadsheet.&lt;/p&gt;
&lt;p&gt;Not a problem for &lt;code&gt;openpyxl&lt;/code&gt;!&lt;/p&gt;
&lt;h3 id=&quot;learning-some-basic-excel-terminology&quot;&gt;Learning Some Basic Excel Terminology&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s a quick list of basic terms you&amp;rsquo;ll see when you&amp;rsquo;re working with Excel spreadsheets:&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;Term&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Spreadsheet or Workbook&lt;/td&gt;
&lt;td&gt;A &lt;strong&gt;Spreadsheet&lt;/strong&gt; is the main file you are creating or working with.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worksheet or Sheet&lt;/td&gt;
&lt;td&gt;A &lt;strong&gt;Sheet&lt;/strong&gt; is used to split different kinds of content within the same spreadsheet. A &lt;strong&gt;Spreadsheet&lt;/strong&gt; can have one or more &lt;strong&gt;Sheets&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Column&lt;/td&gt;
&lt;td&gt;A &lt;strong&gt;Column&lt;/strong&gt; is a vertical line, and it&amp;rsquo;s represented by an uppercase letter: &lt;em&gt;A&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Row&lt;/td&gt;
&lt;td&gt;A &lt;strong&gt;Row&lt;/strong&gt; is a horizontal line, and it&amp;rsquo;s represented by a number: &lt;em&gt;1&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cell&lt;/td&gt;
&lt;td&gt;A &lt;strong&gt;Cell&lt;/strong&gt; is a combination of &lt;strong&gt;Column&lt;/strong&gt; and &lt;strong&gt;Row&lt;/strong&gt;, represented by both an uppercase letter and a number: &lt;em&gt;A1&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 id=&quot;getting-started-with-openpyxl&quot;&gt;Getting Started With openpyxl&lt;/h3&gt;
&lt;p&gt;Now that you&amp;rsquo;re aware of the benefits of a tool like &lt;code&gt;openpyxl&lt;/code&gt;, let&amp;rsquo;s get down to it and start by installing the package. For this tutorial, you should use Python 3.7 and openpyxl 2.6.2. To install the package, you can do 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;gp&quot;&gt;$&lt;/span&gt; pip install openpyxl
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After you install the package, you should be able to create a super simple spreadsheet with the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A1&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;hello&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;B1&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;world!&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_world.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code above should create a file called &lt;code&gt;hello_world.xlsx&lt;/code&gt; in the folder you are using to run the code. If you open that file with Excel you should see something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_16.54.45.e646867e4dbb.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/Screenshot_2019-06-24_16.54.45.e646867e4dbb.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_16.54.45.e646867e4dbb.png&amp;amp;w=540&amp;amp;sig=4c3acdcf35f528b6ed0cf6e299c2575781934414 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_16.54.45.e646867e4dbb.png&amp;amp;w=1080&amp;amp;sig=328d4ff12cec767d684f5b7666380d9f23a2a548 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_16.54.45.e646867e4dbb.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;A Simple Hello World Spreadsheet&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Woohoo&lt;/em&gt;, your first spreadsheet created!&lt;/p&gt;
&lt;h2 id=&quot;reading-excel-spreadsheets-with-openpyxl&quot;&gt;Reading Excel Spreadsheets With openpyxl&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start with the most essential thing one can do with a spreadsheet: read it.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll go from a straightforward approach to reading a spreadsheet to more complex examples where you read the data and convert it into more useful Python structures.&lt;/p&gt;
&lt;h3 id=&quot;dataset-for-this-tutorial&quot;&gt;Dataset for This Tutorial&lt;/h3&gt;
&lt;p&gt;Before you dive deep into some code examples, you should &lt;strong&gt;download this sample dataset&lt;/strong&gt; and store it somewhere as &lt;code&gt;sample.xlsx&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Dataset:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/optins/view/openpyxl-sample-dataset/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-openpyxl-sample-dataset&quot; data-focus=&quot;false&quot;&gt;Click here to download the dataset for the openpyxl exercise you&#39;ll be following in this tutorial.&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;This is one of the datasets you&amp;rsquo;ll be using throughout this tutorial, and it&amp;rsquo;s a spreadsheet with a sample of real data from Amazon&amp;rsquo;s online product reviews. This dataset is only a tiny fraction of what Amazon &lt;a href=&quot;https://registry.opendata.aws/amazon-reviews/&quot;&gt;provides&lt;/a&gt;, but for testing purposes, it&amp;rsquo;s more than enough.&lt;/p&gt;
&lt;h3 id=&quot;a-simple-approach-to-reading-an-excel-spreadsheet&quot;&gt;A Simple Approach to Reading an Excel Spreadsheet&lt;/h3&gt;
&lt;p&gt;Finally, let&amp;rsquo;s start reading some spreadsheets! To begin with, open our sample spreadsheet:&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;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample.xlsx&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Sheet 1&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;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;Worksheet &amp;quot;Sheet 1&amp;quot;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Sheet 1&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the code above, you first open the spreadsheet &lt;code&gt;sample.xlsx&lt;/code&gt; using &lt;code&gt;load_workbook()&lt;/code&gt;, and then you can use &lt;code&gt;workbook.sheetnames&lt;/code&gt; to see all the sheets you have available to work with. After that,  &lt;code&gt;workbook.active&lt;/code&gt; selects the first available sheet and, in this case, you can see that it selects &lt;strong&gt;Sheet 1&lt;/strong&gt; automatically. Using these methods is the default way of opening a spreadsheet, and you&amp;rsquo;ll see it many times during this tutorial.&lt;/p&gt;
&lt;p&gt;Now, after opening a spreadsheet, you can easily retrieve data from it 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;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A1&amp;gt;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;marketplace&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;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;F10&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;G-Shock Men&amp;#39;s Grey Sport Watch&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To return the actual value of a cell, you need to do &lt;code&gt;.value&lt;/code&gt;. Otherwise, you&amp;rsquo;ll get the main &lt;code&gt;Cell&lt;/code&gt; object. You can also use the method &lt;code&gt;.cell()&lt;/code&gt; to retrieve a cell using index notation. Remember to add &lt;code&gt;.value&lt;/code&gt; to get the actual value and not a &lt;code&gt;Cell&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;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;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.F10&amp;gt;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;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;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;G-Shock Men&amp;#39;s Grey Sport Watch&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can see that the results returned are the same, no matter which way you decide to go with. However, in this tutorial, you&amp;rsquo;ll be mostly using the first approach: &lt;code&gt;[&quot;A1&quot;]&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; Even though in Python you&amp;rsquo;re used to a zero-indexed notation, with spreadsheets you&amp;rsquo;ll always use a one-indexed notation where the first row or column always has index &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The above shows you the quickest way to open a spreadsheet. However, you can pass additional parameters to change the way a spreadsheet is loaded.&lt;/p&gt;
&lt;h4 id=&quot;additional-reading-options&quot;&gt;Additional Reading Options&lt;/h4&gt;
&lt;p&gt;There are a few arguments you can pass to &lt;code&gt;load_workbook()&lt;/code&gt; that change the way a spreadsheet is loaded. The most important ones are the following two Booleans:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;read_only&lt;/strong&gt; loads a spreadsheet in read-only mode allowing you to open very large Excel files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;data_only&lt;/strong&gt; ignores loading formulas and instead loads only the resulting values.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;importing-data-from-a-spreadsheet&quot;&gt;Importing Data From a Spreadsheet&lt;/h3&gt;
&lt;p&gt;Now that you&amp;rsquo;ve learned the basics about loading a spreadsheet, it&amp;rsquo;s about time you get to the fun part: &lt;strong&gt;the iteration and actual usage of the values within the spreadsheet&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This section is where you&amp;rsquo;ll learn all the different ways you can iterate through the data, but also how to convert that data into something usable and, more importantly, how to do it in a Pythonic way.&lt;/p&gt;
&lt;h4 id=&quot;iterating-through-the-data&quot;&gt;Iterating Through the Data&lt;/h4&gt;
&lt;p&gt;There are a few different ways you can iterate through the data depending on your needs.&lt;/p&gt;
&lt;p&gt;You can slice the data with a combination of columns and rows:&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;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A1:C2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;((&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.C1&amp;gt;),&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; (&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A2&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B2&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.C2&amp;gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can get ranges of rows or columns:&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;# Get all cells from column A&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A1&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A2&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A99&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A100&amp;gt;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Get all cells for a range of columns&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A:B&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;((&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A1&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A2&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A99&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A100&amp;gt;),&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; (&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B1&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B2&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B99&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B100&amp;gt;))&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Get all cells from row 5&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A5&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B5&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.N5&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.O5&amp;gt;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Get all cells for a range of rows&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;((&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A5&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B5&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.N5&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.O5&amp;gt;),&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; (&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A6&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B6&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.N6&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.O6&amp;gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll notice that all of the above examples return a &lt;code&gt;tuple&lt;/code&gt;. If you want to refresh your memory on how to handle &lt;code&gt;tuples&lt;/code&gt; in Python, check out the article on &lt;a href=&quot;https://realpython.com/python-lists-tuples/#python-tuples&quot;&gt;Lists and Tuples in Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are also multiple ways of using normal Python &lt;a href=&quot;https://realpython.com/introduction-to-python-generators/&quot;&gt;generators&lt;/a&gt; to go through the data. The main methods you can use to achieve this are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.iter_rows()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.iter_cols()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both methods can receive the following arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;min_row&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max_row&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;min_col&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max_col&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These arguments are used to set boundaries for the iteration:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                           &lt;span class=&quot;n&quot;&gt;max_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                           &lt;span class=&quot;n&quot;&gt;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                           &lt;span class=&quot;n&quot;&gt;max_col&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.C1&amp;gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A2&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B2&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.C2&amp;gt;)&lt;/span&gt;


&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;column&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                              &lt;span class=&quot;n&quot;&gt;max_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                              &lt;span class=&quot;n&quot;&gt;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                              &lt;span class=&quot;n&quot;&gt;max_col&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A2&amp;gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B2&amp;gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.C1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.C2&amp;gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll notice that in the first example, when iterating through the rows using &lt;code&gt;.iter_rows()&lt;/code&gt;, you get one &lt;code&gt;tuple&lt;/code&gt; element per row selected. While when using &lt;code&gt;.iter_cols()&lt;/code&gt; and iterating through columns, you&amp;rsquo;ll get one &lt;code&gt;tuple&lt;/code&gt; per column instead.&lt;/p&gt;
&lt;p&gt;One additional argument you can pass to both methods is the Boolean &lt;code&gt;values_only&lt;/code&gt;. When it&amp;rsquo;s set to &lt;code&gt;True&lt;/code&gt;, the values of the cell are returned, instead of the &lt;code&gt;Cell&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;max_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;max_col&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;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;values_only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;marketplace&amp;#39;, &amp;#39;customer_id&amp;#39;, &amp;#39;review_id&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;US&amp;#39;, 3653882, &amp;#39;R3O9SGZBVQBV76&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you want to iterate through the whole dataset, then you can also use the attributes &lt;code&gt;.rows&lt;/code&gt; or &lt;code&gt;.columns&lt;/code&gt; directly, which are shortcuts to using &lt;code&gt;.iter_rows()&lt;/code&gt; and &lt;code&gt;.iter_cols()&lt;/code&gt; without any 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;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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.A1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.B1&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.C1&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.M100&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.N100&amp;gt;, &amp;lt;Cell &amp;#39;Sheet 1&amp;#39;.O100&amp;gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These shortcuts are very useful when you&amp;rsquo;re iterating through the whole dataset.&lt;/p&gt;
&lt;h4 id=&quot;manipulate-data-using-pythons-default-data-structures&quot;&gt;Manipulate Data Using Python&amp;rsquo;s Default Data Structures&lt;/h4&gt;
&lt;p&gt;Now that you know the basics of iterating through the data in a workbook, let&amp;rsquo;s look at smart ways of converting that data into Python structures.&lt;/p&gt;
&lt;p&gt;As you saw earlier, the result from all iterations comes in the form of &lt;code&gt;tuples&lt;/code&gt;. However, since a &lt;code&gt;tuple&lt;/code&gt; is nothing more than an immutable &lt;code&gt;list&lt;/code&gt;, you can easily access its data and transform it into other structures.&lt;/p&gt;
&lt;p&gt;For example, say you want to extract product information from the &lt;code&gt;sample.xlsx&lt;/code&gt; spreadsheet and into a dictionary where each key is a product ID.&lt;/p&gt;
&lt;p&gt;A straightforward way to do this is to iterate over all the rows, pick the columns you know are related to product information, and then store that in a dictionary. Let&amp;rsquo;s code this out!&lt;/p&gt;
&lt;p&gt;First of all, have a look at the headers and see what information you care most about:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;max_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;values_only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;marketplace&amp;#39;, &amp;#39;customer_id&amp;#39;, &amp;#39;review_id&amp;#39;, &amp;#39;product_id&amp;#39;, ...)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code returns a list of all the column names you have in the spreadsheet. To start, grab the columns with names:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;product_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;product_parent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;product_title&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;product_category&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lucky for you, the columns you need are all next to each other so you can use the &lt;code&gt;min_column&lt;/code&gt; and &lt;code&gt;max_column&lt;/code&gt; to easily get the data you want:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;min_col&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;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;max_col&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;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;values_only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;B00FALQ1ZC&amp;#39;, 937001370, &amp;#39;Invicta Women\&amp;#39;s 15150 &amp;quot;Angel&amp;quot; 18k Yellow...)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;B00D3RGO20&amp;#39;, 484010722, &amp;quot;Kenneth Cole New York Women&amp;#39;s KC4944...)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nice! Now that you know how to get all the important product information you need, let&amp;rsquo;s put that data into a dictionary:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;products&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Using the values_only because you want to return the cells&amp;#39; values&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;min_col&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;n&quot;&gt;max_col&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;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;values_only&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;product_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &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;parent&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;category&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&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;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Using json here to be able to format the output for displaying later&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;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;products&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 returns a JSON similar to this:&lt;/p&gt;
&lt;div class=&quot;highlight json&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;quot;B00FALQ1ZC&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;nt&quot;&gt;&amp;quot;parent&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;937001370&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Invicta Women&amp;#39;s 15150 ...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;quot;category&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Watches&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;quot;B00D3RGO20&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;nt&quot;&gt;&amp;quot;parent&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;484010722&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Kenneth Cole New York ...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;quot;category&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Watches&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here you can see that the output is trimmed to 2 products only, but if you run the script as it is, then you should get 98 products.&lt;/p&gt;
&lt;h4 id=&quot;convert-data-into-python-classes&quot;&gt;Convert Data Into Python Classes&lt;/h4&gt;
&lt;p&gt;To finalize the reading section of this tutorial, let&amp;rsquo;s dive into Python classes and see how you could improve on the example above and better structure the data.&lt;/p&gt;
&lt;p&gt;For this, you&amp;rsquo;ll be using the new Python &lt;a href=&quot;https://realpython.com/python-data-classes/&quot;&gt;Data Classes&lt;/a&gt; that are available from Python 3.7. If you&amp;rsquo;re using an older version of Python, then you can use the default &lt;a href=&quot;https://realpython.com/python3-object-oriented-programming/#classes-in-python&quot;&gt;Classes&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;So, first things first, let&amp;rsquo;s look at the data you have and decide what you want to store and how you want to store it.&lt;/p&gt;
&lt;p&gt;As you saw right at the start, this data comes from Amazon, and it&amp;rsquo;s a list of product reviews. You can check the &lt;a href=&quot;https://s3.amazonaws.com/amazon-reviews-pds/tsv/index.txt&quot;&gt;list of all the columns and their meaning&lt;/a&gt; on Amazon.&lt;/p&gt;
&lt;p&gt;There are two significant elements you can extract from the data available:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;li&gt;Reviews&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A &lt;strong&gt;Product&lt;/strong&gt; has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ID&lt;/li&gt;
&lt;li&gt;Title&lt;/li&gt;
&lt;li&gt;Parent&lt;/li&gt;
&lt;li&gt;Category&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;strong&gt;Review&lt;/strong&gt; has a few more fields:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ID&lt;/li&gt;
&lt;li&gt;Customer ID&lt;/li&gt;
&lt;li&gt;Stars&lt;/li&gt;
&lt;li&gt;Headline&lt;/li&gt;
&lt;li&gt;Body&lt;/li&gt;
&lt;li&gt;Date&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can ignore a few of the review fields to make things a bit simpler.&lt;/p&gt;
&lt;p&gt;So, a straightforward implementation of these two classes could be written in a separate file &lt;code&gt;classes.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;datetime&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dataclasses&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataclass&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@dataclass&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&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;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;category&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;nd&quot;&gt;@dataclass&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;customer_id&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;stars&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;headline&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;body&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;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After defining your data classes, you need to convert the data from the spreadsheet into these new structures.&lt;/p&gt;
&lt;p&gt;Before doing the conversion, it&amp;rsquo;s worth looking at our header again and creating a mapping between columns and the fields you need:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;max_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                             &lt;span class=&quot;n&quot;&gt;values_only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;marketplace&amp;#39;, &amp;#39;customer_id&amp;#39;, &amp;#39;review_id&amp;#39;, &amp;#39;product_id&amp;#39;, ...)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Or an alternative&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;cell&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;marketplace&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;customer_id&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;review_id&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;product_id&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;product_parent&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s create a file &lt;code&gt;mapping.py&lt;/code&gt; where you have a list of all the field names and their column location (zero-indexed) on the spreadsheet:&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;# Product fields&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;PRODUCT_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;PRODUCT_PARENT&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;n&quot;&gt;PRODUCT_TITLE&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;n&quot;&gt;PRODUCT_CATEGORY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Review fields&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;REVIEW_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;REVIEW_CUSTOMER&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;n&quot;&gt;REVIEW_STARS&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;n&quot;&gt;REVIEW_HEADLINE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;REVIEW_BODY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;REVIEW_DATE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You don&amp;rsquo;t necessarily have to do the mapping above. It&amp;rsquo;s more for readability when parsing the row data, so you don&amp;rsquo;t end up with a lot of magic numbers lying around.&lt;/p&gt;
&lt;p&gt;Finally, let&amp;rsquo;s look at the code needed to parse the spreadsheet data into a list of product and review objects:&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;datetime&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;classes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Review&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;mapping&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PRODUCT_ID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PRODUCT_PARENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PRODUCT_TITLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; \
    &lt;span class=&quot;n&quot;&gt;PRODUCT_CATEGORY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REVIEW_DATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REVIEW_ID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REVIEW_CUSTOMER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; \
    &lt;span class=&quot;n&quot;&gt;REVIEW_STARS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REVIEW_HEADLINE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REVIEW_BODY&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Using the read_only method since you&amp;#39;re not gonna be editing the spreadsheet&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_only&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;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;products&lt;/span&gt; &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;reviews&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Using the values_only because you just want to return the cell value&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values_only&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;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PRODUCT_ID&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;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PRODUCT_PARENT&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;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PRODUCT_TITLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                      &lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PRODUCT_CATEGORY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;products&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;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# You need to parse the date from the spreadsheet into a datetime format&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;spread_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REVIEW_DATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parsed_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strptime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spread_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;%Y-%m-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;review&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REVIEW_ID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;customer_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REVIEW_CUSTOMER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;stars&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REVIEW_STARS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;headline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REVIEW_HEADLINE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REVIEW_BODY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parsed_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;reviews&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;review&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;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reviews&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;After you run the code above, you should get some output 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;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;B00FALQ1ZC&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;mi&quot;&gt;937001370&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;Review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;R3O9SGZBVQBV76&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customer_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3653882&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s it! Now you should have the data in a very simple and digestible class format, and you can start thinking of storing this in a &lt;a href=&quot;https://realpython.com/tutorials/databases/&quot;&gt;Database&lt;/a&gt; or any other type of data storage you like.&lt;/p&gt;
&lt;p&gt;Using this kind of OOP strategy to parse spreadsheets makes handling the data much simpler later on.&lt;/p&gt;
&lt;h3 id=&quot;appending-new-data&quot;&gt;Appending New Data&lt;/h3&gt;
&lt;p&gt;Before you start creating very complex spreadsheets, have a quick look at an example of how to append data to an existing spreadsheet.&lt;/p&gt;
&lt;p&gt;Go back to the first example spreadsheet you created (&lt;code&gt;hello_world.xlsx&lt;/code&gt;) and try opening it and appending some data to it, like this:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Start by opening the spreadsheet and selecting the main sheet&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_world.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Write what you want into a specific cell&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;C1&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;writing ;)&amp;quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Save the spreadsheet&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_world_append.xlsx&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Et voilà&lt;/em&gt;, if you open the new &lt;code&gt;hello_world_append.xlsx&lt;/code&gt; spreadsheet, you&amp;rsquo;ll see the following change:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_17.44.22.e4f18e5abc42.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/Screenshot_2019-06-24_17.44.22.e4f18e5abc42.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_17.44.22.e4f18e5abc42.png&amp;amp;w=540&amp;amp;sig=098886279b90048004feb6dcdbe1c66ac3e231ce 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_17.44.22.e4f18e5abc42.png&amp;amp;w=1080&amp;amp;sig=8619e04c109779499f96dcd8aee01c4cf1ed52eb 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_17.44.22.e4f18e5abc42.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Appending Data to a Spreadsheet&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice the additional &lt;em&gt;writing ;)&lt;/em&gt; on cell &lt;code&gt;C1&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;writing-excel-spreadsheets-with-openpyxl&quot;&gt;Writing Excel Spreadsheets With openpyxl&lt;/h2&gt;
&lt;p&gt;There are a lot of different things you can write to a spreadsheet, from simple text or number values to complex formulas, charts, or even images.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start creating some spreadsheets!&lt;/p&gt;
&lt;h3 id=&quot;creating-a-simple-spreadsheet&quot;&gt;Creating a Simple Spreadsheet&lt;/h3&gt;
&lt;p&gt;Previously, you saw a very quick example of how to write &amp;ldquo;Hello world!&amp;rdquo; into a spreadsheet, so you can start with 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;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;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&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;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_world.xlsx&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;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&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;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A1&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;hello&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;B1&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;world!&amp;quot;&lt;/span&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;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The highlighted lines in the code above are the most important ones for writing. In the code, you can see that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 5&lt;/strong&gt; shows you how to create a new empty workbook.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 8 and 9&lt;/strong&gt; show you how to add data to specific cells.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 11&lt;/strong&gt; shows you how to save the spreadsheet when you&amp;rsquo;re done.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even though these lines above can be straightforward, it&amp;rsquo;s still good to know them well for when things get a bit more complicated.&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 using the &lt;code&gt;hello_world.xlsx&lt;/code&gt; spreadsheet for some of the upcoming examples, so keep it handy.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;One thing you can do to help with coming code examples is add the following method to your Python file or console:&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;print_rows&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;row&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values_only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It makes it easier to print all of your spreadsheet values by just calling &lt;code&gt;print_rows()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;basic-spreadsheet-operations&quot;&gt;Basic Spreadsheet Operations&lt;/h3&gt;
&lt;p&gt;Before you get into the more advanced topics, it&amp;rsquo;s good for you to know how to manage the most simple elements of a spreadsheet.&lt;/p&gt;
&lt;h4 id=&quot;adding-and-updating-cell-values&quot;&gt;Adding and Updating Cell Values&lt;/h4&gt;
&lt;p&gt;You already learned how to add values to a spreadsheet 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;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A1&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;value&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There&amp;rsquo;s another way you can do this, by first selecting a cell and then changing 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;cell&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A1&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;cell&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;Cell &amp;#39;Sheet&amp;#39;.A1&amp;gt;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;hello&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;cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hey&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;cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;hey&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The new value is only stored into the spreadsheet once you call &lt;code&gt;workbook.save()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;openpyxl&lt;/code&gt; creates a cell when adding a value, if that cell didn&amp;rsquo;t exist before:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Before, our spreadsheet has only 1 row&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;hello&amp;#39;, &amp;#39;world!&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Try adding a value to row 10&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;B10&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;test&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;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;hello&amp;#39;, &amp;#39;world!&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, &amp;#39;test&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, when trying to add a value to cell &lt;code&gt;B10&lt;/code&gt;, you end up with a tuple with 10 rows, just so you can have that &lt;em&gt;test&lt;/em&gt; value.&lt;/p&gt;
&lt;h4 id=&quot;managing-rows-and-columns&quot;&gt;Managing Rows and Columns&lt;/h4&gt;
&lt;p&gt;One of the most common things you have to do when manipulating spreadsheets is adding or removing rows and columns. The &lt;code&gt;openpyxl&lt;/code&gt; package allows you to do that in a very straightforward way by using the methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.insert_rows()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.delete_rows()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.insert_cols()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.delete_cols()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every single one of those methods can receive two arguments:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;idx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;amount&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Using our basic &lt;code&gt;hello_world.xlsx&lt;/code&gt; example again, let&amp;rsquo;s see how these methods work:&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;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;hello&amp;#39;, &amp;#39;world!&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Insert a column before the existing column 1 (&amp;quot;A&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert_cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, &amp;#39;hello&amp;#39;, &amp;#39;world!&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Insert 5 columns between column 2 (&amp;quot;B&amp;quot;) and 3 (&amp;quot;C&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert_cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, &amp;#39;hello&amp;#39;, None, None, None, None, None, &amp;#39;world!&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Delete the created columns&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete_cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete_cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;hello&amp;#39;, &amp;#39;world!&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Insert a new row in the beginning&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;hello&amp;#39;, &amp;#39;world!&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Insert 3 new rows in the beginning&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&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;amount&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(None, None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;hello&amp;#39;, &amp;#39;world!&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Delete the first 4 rows&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&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;amount&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;hello&amp;#39;, &amp;#39;world!&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The only thing you need to remember is that when inserting new data (rows or columns), the insertion happens &lt;strong&gt;before&lt;/strong&gt; the &lt;code&gt;idx&lt;/code&gt; parameter.&lt;/p&gt;
&lt;p&gt;So, if you do &lt;code&gt;insert_rows(1)&lt;/code&gt;, it inserts a new row &lt;strong&gt;before&lt;/strong&gt; the existing first row.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s the same for columns: when you call &lt;code&gt;insert_cols(2)&lt;/code&gt;, it inserts a new column right &lt;strong&gt;before&lt;/strong&gt; the already existing second column (&lt;code&gt;B&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;However, when deleting rows or columns, &lt;code&gt;.delete_...&lt;/code&gt; deletes data &lt;strong&gt;starting from&lt;/strong&gt; the index passed as an argument.&lt;/p&gt;
&lt;p&gt;For example, when doing &lt;code&gt;delete_rows(2)&lt;/code&gt; it deletes row &lt;code&gt;2&lt;/code&gt;, and when doing &lt;code&gt;delete_cols(3)&lt;/code&gt; it deletes the third column (&lt;code&gt;C&lt;/code&gt;).&lt;/p&gt;
&lt;h4 id=&quot;managing-sheets&quot;&gt;Managing Sheets&lt;/h4&gt;
&lt;p&gt;Sheet management is also one of those things you might need to know, even though it might be something that you don&amp;rsquo;t use that often.&lt;/p&gt;
&lt;p&gt;If you look back at the code examples from this tutorial, you&amp;rsquo;ll notice the following recurring piece of code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the way to select the default sheet from a spreadsheet. However, if you&amp;rsquo;re opening a spreadsheet with multiple sheets, then you can always select a specific one 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;c1&quot;&gt;# Let&amp;#39;s say you have two sheets: &amp;quot;Products&amp;quot; and &amp;quot;Company Sales&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Products&amp;#39;, &amp;#39;Company Sales&amp;#39;]&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# You can select a sheet using its title&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;products_sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Products&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;sales_sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Company Sales&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also change a sheet title very easily:&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Products&amp;#39;, &amp;#39;Company Sales&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;products_sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Products&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;products_sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;New Products&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;New Products&amp;#39;, &amp;#39;Company Sales&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you want to create or delete sheets, then you can also do that with &lt;code&gt;.create_sheet()&lt;/code&gt; and &lt;code&gt;.remove()&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Products&amp;#39;, &amp;#39;Company Sales&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;operations_sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Operations&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Products&amp;#39;, &amp;#39;Company Sales&amp;#39;, &amp;#39;Operations&amp;#39;]&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# You can also define the position to create the sheet at&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hr_sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;HR&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;HR&amp;#39;, &amp;#39;Products&amp;#39;, &amp;#39;Company Sales&amp;#39;, &amp;#39;Operations&amp;#39;]&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# To remove them, just pass the sheet as an argument to the .remove()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;operations_sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;HR&amp;#39;, &amp;#39;Products&amp;#39;, &amp;#39;Company Sales&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hr_sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Products&amp;#39;, &amp;#39;Company Sales&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;One other thing you can do is make duplicates of a sheet using &lt;code&gt;copy_worksheet()&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Products&amp;#39;, &amp;#39;Company Sales&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;products_sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Products&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy_worksheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;products_sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;Worksheet &amp;quot;Products Copy&amp;quot;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheetnames&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Products&amp;#39;, &amp;#39;Company Sales&amp;#39;, &amp;#39;Products Copy&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you open your spreadsheet after saving the above code, you&amp;rsquo;ll notice that the sheet &lt;em&gt;Products Copy&lt;/em&gt; is a duplicate of the sheet &lt;em&gt;Products&lt;/em&gt;.&lt;/p&gt;
&lt;h4 id=&quot;freezing-rows-and-columns&quot;&gt;Freezing Rows and Columns&lt;/h4&gt;
&lt;p&gt;Something that you might want to do when working with big spreadsheets is to freeze a few rows or columns, so they remain visible when you scroll right or down.&lt;/p&gt;
&lt;p&gt;Freezing data allows you to keep an eye on important rows or columns, regardless of where you scroll in the spreadsheet.&lt;/p&gt;
&lt;p&gt;Again, &lt;code&gt;openpyxl&lt;/code&gt; also has a way to accomplish this by using the worksheet &lt;code&gt;freeze_panes&lt;/code&gt; attribute. For this example, go back to our &lt;code&gt;sample.xlsx&lt;/code&gt; spreadsheet and try doing the following:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample.xlsx&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;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;freeze_panes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C2&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_frozen.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you open the &lt;code&gt;sample_frozen.xlsx&lt;/code&gt; spreadsheet in your favorite spreadsheet editor, you&amp;rsquo;ll notice that row &lt;code&gt;1&lt;/code&gt; and columns &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; are frozen and are always visible no matter where you navigate within the spreadsheet.&lt;/p&gt;
&lt;p&gt;This feature is handy, for example, to keep headers within sight, so you always know what each column represents.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how it looks in the editor:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_18.12.20.55694a0781f8.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/Screenshot_2019-06-24_18.12.20.55694a0781f8.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.12.20.55694a0781f8.png&amp;amp;w=540&amp;amp;sig=5826de23e5df2e08d625844698fc3a29b32ee7b2 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.12.20.55694a0781f8.png&amp;amp;w=1080&amp;amp;sig=c3abe2321f00372d975bbbf033f3ebe3687eb09f 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_18.12.20.55694a0781f8.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Frozen Rows and Columns&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice how you&amp;rsquo;re at the end of the spreadsheet, and yet, you can see both row &lt;code&gt;1&lt;/code&gt; and columns &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&quot;adding-filters&quot;&gt;Adding Filters&lt;/h4&gt;
&lt;p&gt;You can use &lt;code&gt;openpyxl&lt;/code&gt; to add filters and sorts to your spreadsheet. However, when you open the spreadsheet, the data won&amp;rsquo;t be rearranged according to these sorts and filters.&lt;/p&gt;
&lt;p&gt;At first, this might seem like a pretty useless feature, but when you&amp;rsquo;re programmatically creating a spreadsheet that is going to be sent and used by somebody else, it&amp;rsquo;s still nice to at least create the filters and allow people to use it afterward.&lt;/p&gt;
&lt;p&gt;The code below is an example of how you would add some filters to our existing &lt;code&gt;sample.xlsx&lt;/code&gt; spreadsheet:&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;# Check the used spreadsheet space using the attribute &amp;quot;dimensions&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimensions&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;A1:O100&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;A1:O100&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_with_filters.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should now see the filters created when opening the spreadsheet in your editor:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_18.20.35.5fdbfe805194.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/Screenshot_2019-06-24_18.20.35.5fdbfe805194.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.20.35.5fdbfe805194.png&amp;amp;w=540&amp;amp;sig=c1d7ad4f2dfc03fc8730e3babf9000ac74170c7d 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.20.35.5fdbfe805194.png&amp;amp;w=1080&amp;amp;sig=27e888a967ddc112f1e824be671a15e2c111fe6c 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_18.20.35.5fdbfe805194.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Filters&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You don&amp;rsquo;t have to use &lt;code&gt;sheet.dimensions&lt;/code&gt; if you know precisely which part of the spreadsheet you want to apply filters to.&lt;/p&gt;
&lt;h3 id=&quot;adding-formulas&quot;&gt;Adding Formulas&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Formulas&lt;/strong&gt; (or &lt;strong&gt;formulae&lt;/strong&gt;) are one of the most powerful features of spreadsheets.&lt;/p&gt;
&lt;p&gt;They gives you the power to apply specific mathematical equations to a range of cells. Using formulas with &lt;code&gt;openpyxl&lt;/code&gt; is as simple as editing the value of a cell.&lt;/p&gt;
&lt;p&gt;You can see the list of formulas supported by &lt;code&gt;openpyxl&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;openpyxl.utils&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FORMULAE&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FORMULAE&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;frozenset({&amp;#39;ABS&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;ACCRINT&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;ACCRINTM&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;ACOS&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;ACOSH&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;AMORDEGRC&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;AMORLINC&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;AND&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;YEARFRAC&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;YIELD&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;YIELDDISC&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;YIELDMAT&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           &amp;#39;ZTEST&amp;#39;})&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s add some formulas to our &lt;code&gt;sample.xlsx&lt;/code&gt; spreadsheet.&lt;/p&gt;
&lt;p&gt;Starting with something easy, let&amp;rsquo;s check the average star rating for the 99 reviews within the spreadsheet:&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;# Star rating is column &amp;quot;H&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;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;P2&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;=AVERAGE(H2:H100)&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_formulas.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you open the spreadsheet now and go to cell &lt;code&gt;P2&lt;/code&gt;, you should see that its value is: &lt;em&gt;4.18181818181818&lt;/em&gt;. Have a look in the editor:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_18.33.09.7c2633f706cc.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/Screenshot_2019-06-24_18.33.09.7c2633f706cc.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.33.09.7c2633f706cc.png&amp;amp;w=540&amp;amp;sig=5d7a9eb97acf524d5d2b9b93ae0e9214bbcf95c8 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.33.09.7c2633f706cc.png&amp;amp;w=1080&amp;amp;sig=8af67321cb101fb2f30fd0ca2bdcc62de35c9334 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_18.33.09.7c2633f706cc.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Average Formula&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can use the same methodology to add any formulas to your spreadsheet. For example, let&amp;rsquo;s count the number of reviews that had helpful votes:&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;# The helpful votes are counted on column &amp;quot;I&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;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;P3&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;s1&quot;&gt;&amp;#39;=COUNTIF(I2:I100, &amp;quot;&amp;gt;0&amp;quot;)&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;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_formulas.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should get the number &lt;code&gt;21&lt;/code&gt; on your &lt;code&gt;P3&lt;/code&gt; spreadsheet cell like so:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_18.35.24.e26e97b0c9c0.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/Screenshot_2019-06-24_18.35.24.e26e97b0c9c0.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.35.24.e26e97b0c9c0.png&amp;amp;w=540&amp;amp;sig=0ec4c4c12a792a1a393e0273855282bfa0594d53 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.35.24.e26e97b0c9c0.png&amp;amp;w=1080&amp;amp;sig=67b399b8cb79ddbe7285da0325fe8f6b9edf3ecc 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_18.35.24.e26e97b0c9c0.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Average and CountIf Formula&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll have to make sure that the strings within a formula are always in double quotes, so you either have to use single quotes around the formula like in the example above or you&amp;rsquo;ll have to escape the double quotes inside the formula: &lt;code&gt;&quot;=COUNTIF(I2:I100, \&quot;&amp;gt;0\&quot;)&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are a ton of other formulas you can add to your spreadsheet using the same procedure you tried above. Give it a go yourself!&lt;/p&gt;
&lt;h3 id=&quot;adding-styles&quot;&gt;Adding Styles&lt;/h3&gt;
&lt;p&gt;Even though styling a spreadsheet might not be something you would do every day, it&amp;rsquo;s still good to know how to do it.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;openpyxl&lt;/code&gt;, you can apply multiple styling options to your spreadsheet, including fonts, borders, colors, and so on. Have a look at the &lt;code&gt;openpyxl&lt;/code&gt; &lt;a href=&quot;https://openpyxl.readthedocs.io/en/stable/styles.html&quot;&gt;documentation&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;p&gt;You can also choose to either apply a style directly to a cell or create a template and reuse it to apply styles to multiple cells.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start by having a look at simple cell styling, using our &lt;code&gt;sample.xlsx&lt;/code&gt; again as the base spreadsheet:&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;# Import necessary style classes&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;openpyxl.styles&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Alignment&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;n&quot;&gt;Side&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Create a few styles&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bold_font&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bold&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;big_red_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;RED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;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;center_aligned_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Alignment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;horizontal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;center&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;double_border_side&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Side&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;border_style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;double&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;square_border&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double_border_side&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;right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double_border_side&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;bottom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double_border_side&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;left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double_border_side&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Style some cells!&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bold_font&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A3&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;big_red_text&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A4&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;center_aligned_text&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;border&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;square_border&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_styles.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you open your spreadsheet now, you should see quite a few different styles on the first 5 cells of column &lt;code&gt;A&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_18.43.15.e3aeb3fb06e3.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/Screenshot_2019-06-24_18.43.15.e3aeb3fb06e3.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.43.15.e3aeb3fb06e3.png&amp;amp;w=540&amp;amp;sig=ecc21878006697a6135ae515442642a95ab2bfb6 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.43.15.e3aeb3fb06e3.png&amp;amp;w=1080&amp;amp;sig=6f0ef4a148f1ca5a588e0cb2c02b0c9aad4246f2 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_18.43.15.e3aeb3fb06e3.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Simple Cell Styles&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There you go. You got:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A2&lt;/strong&gt; with the text in bold&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A3&lt;/strong&gt; with the text in red and bigger font size&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A4&lt;/strong&gt; with the text centered&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A5&lt;/strong&gt; with a square border around the text&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; For the colors, you can also use HEX codes instead by doing  &lt;code&gt;Font(color=&quot;C70E0F&quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can also combine styles by simply adding them to the cell at the same time:&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;# Reusing the same styles from the example above&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A6&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;center_aligned_text&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A6&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;big_red_text&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A6&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;border&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;square_border&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_styles.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Have a look at cell &lt;code&gt;A6&lt;/code&gt; here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_18.46.04.314517930065.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/Screenshot_2019-06-24_18.46.04.314517930065.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.46.04.314517930065.png&amp;amp;w=540&amp;amp;sig=290bbf523eb24ac8c9741daf86701ca57cad4b96 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.46.04.314517930065.png&amp;amp;w=1080&amp;amp;sig=9decedef154c2138e26b287f2186213142650f6e 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_18.46.04.314517930065.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Coupled Cell Styles&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you want to apply multiple styles to one or several cells, you can use a &lt;code&gt;NamedStyle&lt;/code&gt; class instead, which is like a style template that you can use over and over again. Have a look at the example 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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl.styles&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NamedStyle&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;# Let&amp;#39;s create a style template for the header row&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NamedStyle&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;header&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;header&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bold&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;Border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Side&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;border_style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;thin&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;header&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Alignment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;horizontal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;center&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertical&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;center&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;# Now let&amp;#39;s apply this to all first row (header) cells&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;header_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header_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;cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_styles.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you open the spreadsheet now, you should see that its first row is bold, the text is aligned to the center, and there&amp;rsquo;s a small bottom border! Have a look below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_18.48.33.4bc57d1b24d5.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/Screenshot_2019-06-24_18.48.33.4bc57d1b24d5.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.48.33.4bc57d1b24d5.png&amp;amp;w=540&amp;amp;sig=199107a0c9ea60fbf1dfcc078a7680b43faeef3a 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.48.33.4bc57d1b24d5.png&amp;amp;w=1080&amp;amp;sig=af3e5225e36a24dea088e8c175da02050bb5dda9 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_18.48.33.4bc57d1b24d5.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Named Styles&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you saw above, there are many options when it comes to styling, and it depends on the use case, so feel free to check &lt;code&gt;openpyxl&lt;/code&gt; &lt;a href=&quot;https://openpyxl.readthedocs.io/en/stable/styles.html&quot;&gt;documentation&lt;/a&gt; and see what other things you can do.&lt;/p&gt;
&lt;h3 id=&quot;conditional-formatting&quot;&gt;Conditional Formatting&lt;/h3&gt;
&lt;p&gt;This feature is one of my personal favorites when it comes to adding styles to a spreadsheet.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a much more powerful approach to styling because it dynamically applies styles according to how the data in the spreadsheet changes.&lt;/p&gt;
&lt;p&gt;In a nutshell, &lt;strong&gt;conditional formatting&lt;/strong&gt; allows you to specify a list of styles to apply to a cell (or cell range) according to specific conditions.&lt;/p&gt;
&lt;p&gt;For example, a widespread use case is to have a balance sheet where all the negative totals are in red, and the positive ones are in green. This formatting makes it much more efficient to spot good vs bad periods.&lt;/p&gt;
&lt;p&gt;Without further ado, let&amp;rsquo;s pick our favorite spreadsheet&amp;mdash;&lt;code&gt;sample.xlsx&lt;/code&gt;&amp;mdash;and add some conditional formatting.&lt;/p&gt;
&lt;p&gt;You can start by adding a simple one that adds a red background to all reviews with less than 3 stars:&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;openpyxl.styles&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PatternFill&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;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;openpyxl.styles.differential&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DifferentialStyle&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;openpyxl.formatting.rule&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rule&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;red_background&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PatternFill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bgColor&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;RED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diff_style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DifferentialStyle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;red_background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;expression&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dxf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diff_style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;formula&lt;/span&gt; &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;$H1&amp;lt;3&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditional_formatting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A1:O100&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_conditional_formatting.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you&amp;rsquo;ll see all the reviews with a star rating below 3 marked with a red background:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_18.55.41.17f234a186c6.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/Screenshot_2019-06-24_18.55.41.17f234a186c6.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.55.41.17f234a186c6.png&amp;amp;w=540&amp;amp;sig=f3c141c2fe708c031c32c083cb038a736fd8da87 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_18.55.41.17f234a186c6.png&amp;amp;w=1080&amp;amp;sig=9ded3045cee09d34cd6f5dada7a4eea669ac4808 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_18.55.41.17f234a186c6.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Simple Conditional Formatting&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Code-wise, the only things that are new here are the objects &lt;code&gt;DifferentialStyle&lt;/code&gt; and &lt;code&gt;Rule&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DifferentialStyle&lt;/code&gt;&lt;/strong&gt; is quite similar to &lt;code&gt;NamedStyle&lt;/code&gt;, which you already saw above, and it&amp;rsquo;s used to aggregate multiple styles such as fonts, borders, alignment, and so forth.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Rule&lt;/code&gt;&lt;/strong&gt; is responsible for selecting the cells and applying the styles if the cells match the rule&amp;rsquo;s logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using a &lt;code&gt;Rule&lt;/code&gt; object, you can create numerous conditional formatting scenarios.&lt;/p&gt;
&lt;p&gt;However, for simplicity sake, the &lt;code&gt;openpyxl&lt;/code&gt; package offers 3 built-in formats that make it easier to create a few common conditional formatting patterns. These built-ins are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ColorScale&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IconSet&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DataBar&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;strong&gt;ColorScale&lt;/strong&gt; gives you the ability to create color gradients:&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;openpyxl.formatting.rule&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ColorScaleRule&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color_scale_rule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ColorScaleRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;min&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;n&quot;&gt;start_color&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;RED&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;end_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;max&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;n&quot;&gt;end_color&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;GREEN&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Again, let&amp;#39;s add this gradient to the star ratings, column &amp;quot;H&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditional_formatting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;H2:H100&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color_scale_rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_conditional_formatting_color_scale.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you should see a color gradient on column &lt;code&gt;H&lt;/code&gt;, from red to green, according to the star rating:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_19.00.57.26756963c1e9.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/Screenshot_2019-06-24_19.00.57.26756963c1e9.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_19.00.57.26756963c1e9.png&amp;amp;w=540&amp;amp;sig=782964d150a8adc1de811fab78b0accde6357f85 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_19.00.57.26756963c1e9.png&amp;amp;w=1080&amp;amp;sig=4c7c87c194ec0a8eb3a9e73fdabf3ead991e96ea 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_19.00.57.26756963c1e9.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Color Scale Conditional Formatting&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can also add a third color and make two gradients instead:&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;openpyxl.formatting.rule&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ColorScaleRule&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color_scale_rule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ColorScaleRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num&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;n&quot;&gt;start_value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                                  &lt;span class=&quot;n&quot;&gt;start_color&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;RED&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;mid_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num&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;n&quot;&gt;mid_value&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;gp&quot;&gt;... &lt;/span&gt;                                  &lt;span class=&quot;n&quot;&gt;mid_color&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;YELLOW&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;end_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num&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;n&quot;&gt;end_value&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;gp&quot;&gt;... &lt;/span&gt;                                  &lt;span class=&quot;n&quot;&gt;end_color&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;GREEN&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Again, let&amp;#39;s add this gradient to the star ratings, column &amp;quot;H&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditional_formatting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;H2:H100&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color_scale_rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_conditional_formatting_color_scale_3.xlsx&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 time, you&amp;rsquo;ll notice that star ratings between 1 and 3 have a gradient from red to yellow, and star ratings between 3 and 5 have a gradient from yellow to green:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_19.03.30.0de9a2ff9866.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/Screenshot_2019-06-24_19.03.30.0de9a2ff9866.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_19.03.30.0de9a2ff9866.png&amp;amp;w=540&amp;amp;sig=17daddc356c8ff5c78497b200fe57ab69f80617d 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_19.03.30.0de9a2ff9866.png&amp;amp;w=1080&amp;amp;sig=6dcb18f4aa3f8ae0a395ca1e3581f8d4c59805ad 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_19.03.30.0de9a2ff9866.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With 2 Color Scales Conditional Formatting&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;IconSet&lt;/strong&gt; allows you to add an icon to the cell according to 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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl.formatting.rule&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IconSetRule&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;icon_set_rule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IconSetRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;5Arrows&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;num&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;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditional_formatting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;H2:H100&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;icon_set_rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_conditional_formatting_icon_set.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll see a colored arrow next to the star rating. This arrow is red and points down when the value of the cell is 1 and, as the rating gets better, the arrow starts pointing up and becomes green:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_19.07.29.23e75ff46771.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/Screenshot_2019-06-24_19.07.29.23e75ff46771.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_19.07.29.23e75ff46771.png&amp;amp;w=540&amp;amp;sig=388fc68ff53fa2e2d3d5678acfd41f10fa8eccde 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_19.07.29.23e75ff46771.png&amp;amp;w=1080&amp;amp;sig=e33f483f9758189782bb619a6714c948130375aa 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_19.07.29.23e75ff46771.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Icon Set Conditional Formatting&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;openpyxl&lt;/code&gt; package has a &lt;a href=&quot;https://openpyxl.readthedocs.io/en/stable/formatting.html#iconset&quot;&gt;full list&lt;/a&gt; of other icons you can use, besides the arrow.&lt;/p&gt;
&lt;p&gt;Finally, the &lt;strong&gt;DataBar&lt;/strong&gt; allows you to create progress bars:&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;openpyxl.formatting.rule&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataBarRule&lt;/span&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_bar_rule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataBarRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num&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;n&quot;&gt;start_value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;                            &lt;span class=&quot;n&quot;&gt;end_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num&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;n&quot;&gt;end_value&lt;/span&gt;&lt;span class=&quot;o&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;gp&quot;&gt;... &lt;/span&gt;                            &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colors&lt;/span&gt;&lt;span class=&quot;o&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditional_formatting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;H2:H100&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_bar_rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample_conditional_formatting_data_bar.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll now see a green progress bar that gets fuller the closer the star rating is to the number 5:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_19.09.10.ebbe032c088d.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/Screenshot_2019-06-24_19.09.10.ebbe032c088d.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_19.09.10.ebbe032c088d.png&amp;amp;w=540&amp;amp;sig=a7b8e3515fde3ff6b662ff1780cbc290da9ce2ad 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_19.09.10.ebbe032c088d.png&amp;amp;w=1080&amp;amp;sig=1e3d2befc147a43c5b98061cf5888abf22ca4c4a 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_19.09.10.ebbe032c088d.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Data Bar Conditional Formatting&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, there are a lot of cool things you can do with conditional formatting.&lt;/p&gt;
&lt;p&gt;Here, you saw only a few examples of what you can achieve with it, but check the &lt;code&gt;openpyxl&lt;/code&gt; &lt;a href=&quot;https://openpyxl.readthedocs.io/en/stable/formatting.html&quot;&gt;documentation&lt;/a&gt; to see a bunch of other options.&lt;/p&gt;
&lt;h3 id=&quot;adding-images&quot;&gt;Adding Images&lt;/h3&gt;
&lt;p&gt;Even though images are not something that you&amp;rsquo;ll often see in a spreadsheet, it&amp;rsquo;s quite cool to be able to add them. Maybe you can use it for branding purposes or to make spreadsheets more personal.&lt;/p&gt;
&lt;p&gt;To be able to load images to a spreadsheet using &lt;code&gt;openpyxl&lt;/code&gt;, you&amp;rsquo;ll have to install &lt;code&gt;Pillow&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 Pillow
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Apart from that, you&amp;rsquo;ll also need an image. For this example, you can grab the &lt;em&gt;Real Python&lt;/em&gt; logo below and convert it from &lt;code&gt;.webp&lt;/code&gt; to &lt;code&gt;.png&lt;/code&gt; using an online converter such as &lt;a href=&quot;https://cloudconvert.com/webp-to-png&quot;&gt;cloudconvert.com&lt;/a&gt;, save the final file as &lt;code&gt;logo.png&lt;/code&gt;, and copy it to the root folder where you&amp;rsquo;re running your examples:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/real-python-logo-round.4d95338e8944.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-25&quot; src=&quot;https://files.realpython.com/media/real-python-logo-round.4d95338e8944.png&quot; width=&quot;1500&quot; height=&quot;1500&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/real-python-logo-round.4d95338e8944.png&amp;amp;w=375&amp;amp;sig=e431a39c9d7f2d5963a81687571a41288c359142 375w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/real-python-logo-round.4d95338e8944.png&amp;amp;w=750&amp;amp;sig=a098752adfc378feee6bc69748af593ed078b8c0 750w, https://files.realpython.com/media/real-python-logo-round.4d95338e8944.png 1500w&quot; sizes=&quot;75vw&quot; alt=&quot;Real Python Logo&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Afterward, this is the code you need to import that image into the &lt;code&gt;hello_word.xlsx&lt;/code&gt; spreadsheet:&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;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl.drawing.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;c1&quot;&gt;# Let&amp;#39;s use the hello_world spreadsheet since it has less data&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_world.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logo&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;s2&quot;&gt;&amp;quot;logo.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# A bit of resizing to not fill the whole spreadsheet with the logo&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logo&lt;/span&gt;&lt;span class=&quot;o&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;150&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;A3&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_world_logo.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You have an image on your spreadsheet! Here it is:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_20.05.30.2a69f2a77f68.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/Screenshot_2019-06-24_20.05.30.2a69f2a77f68.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_20.05.30.2a69f2a77f68.png&amp;amp;w=540&amp;amp;sig=574c2c425c011fa21e790f7cd4a41547f2449b01 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_20.05.30.2a69f2a77f68.png&amp;amp;w=1080&amp;amp;sig=e6b9c78c7daa929ae86f887d560c3f50f0851d5d 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_20.05.30.2a69f2a77f68.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Image&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The image&amp;rsquo;s left top corner is on the cell you chose, in this case, &lt;code&gt;A3&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;adding-pretty-charts&quot;&gt;Adding Pretty Charts&lt;/h3&gt;
&lt;p&gt;Another powerful thing you can do with spreadsheets is create an incredible variety of charts. &lt;/p&gt;
&lt;p&gt;Charts are a great way to visualize and understand loads of data quickly. There are a lot of different chart types: bar chart, pie chart, line chart, and so on. &lt;code&gt;openpyxl&lt;/code&gt; has support for a lot of them.&lt;/p&gt;
&lt;p&gt;Here, you&amp;rsquo;ll see only a couple of examples of charts because the theory behind it is the same for every single chart type:&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 few of the chart types that &lt;code&gt;openpyxl&lt;/code&gt; currently doesn&amp;rsquo;t have support for are Funnel, Gantt, Pareto, Treemap, Waterfall, Map, and Sunburst.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For any chart you want to build, you&amp;rsquo;ll need to define the chart type: &lt;code&gt;BarChart&lt;/code&gt;, &lt;code&gt;LineChart&lt;/code&gt;, and so forth, plus the data to be used for the chart, which is called &lt;code&gt;Reference&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Before you can build your chart, you need to define what data you want to see represented in it. Sometimes, you can use the dataset as is, but other times you need to massage the data a bit to get additional information.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start by building a new workbook with some sample data:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;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;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&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;openpyxl.chart&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BarChart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&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;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&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;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&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;c1&quot;&gt;# Let&amp;#39;s create some sample sales data&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt; &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; 9 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Product&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Online&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Store&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;    &lt;span class=&quot;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;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;45&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;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;40&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;lineno&quot;&gt;12 &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;40&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;lineno&quot;&gt;13 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&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;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&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;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&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 class=&quot;lineno&quot;&gt;16 &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;20&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;lineno&quot;&gt;17 &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;lineno&quot;&gt;19 &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;rows&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;sheet&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;row&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 going to start by creating a &lt;strong&gt;bar chart&lt;/strong&gt; that displays the total number of sales per product:&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;22 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BarChart&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;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worksheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&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;min_row&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;lineno&quot;&gt;25 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;max_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;max_col&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;lineno&quot;&gt;28 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;titles_from_data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;E2&amp;quot;&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;lineno&quot;&gt;32 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;chart.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There you have it. Below, you can see a very straightforward bar chart  showing the difference between &lt;strong&gt;online&lt;/strong&gt; product sales online and &lt;strong&gt;in-store&lt;/strong&gt; product sales:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_20.59.43.7eac35127b97.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/Screenshot_2019-06-24_20.59.43.7eac35127b97.png&quot; width=&quot;2160&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_20.59.43.7eac35127b97.png&amp;amp;w=540&amp;amp;sig=bcdfa015a56b903169702ddbeb1ec06c8d67bc87 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_20.59.43.7eac35127b97.png&amp;amp;w=1080&amp;amp;sig=904be9b2a172b3ae7436311c9d05f6a9ad8ae451 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_20.59.43.7eac35127b97.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Bar Chart&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Like with images, the top left corner of the chart is on the cell you added the chart to. In your case, it was on cell &lt;code&gt;E2&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; Depending on whether you&amp;rsquo;re using Microsoft Excel or an open-source alternative (LibreOffice or OpenOffice), the chart might look slightly different.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Try creating a &lt;strong&gt;line chart&lt;/strong&gt; instead, changing the data a bit:&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;random&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;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&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;openpyxl.chart&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LineChart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&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;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&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;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&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;c1&quot;&gt;# Let&amp;#39;s create some sample sales data&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt; &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;10 &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;January&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;February&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;March&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;April&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;s2&quot;&gt;&amp;quot;May&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;June&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;July&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;August&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;September&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;s2&quot;&gt;&amp;quot;October&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;November&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;December&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;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;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;mi&quot;&gt;2&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;15 &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;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;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;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;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sheet&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;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;                           &lt;span class=&quot;n&quot;&gt;max_row&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;lineno&quot;&gt;23 &lt;/span&gt;                           &lt;span class=&quot;n&quot;&gt;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;                           &lt;span class=&quot;n&quot;&gt;max_col&lt;/span&gt;&lt;span class=&quot;o&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;lineno&quot;&gt;25 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&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;26 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;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;randrange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the above code, you&amp;rsquo;ll be able to generate some random data regarding the sales of 3 different products across a whole year.&lt;/p&gt;
&lt;p&gt;Once that&amp;rsquo;s done, you can very easily create a line chart with the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LineChart&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;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worksheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&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;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;max_row&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;lineno&quot;&gt;32 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;min_col&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;lineno&quot;&gt;33 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;max_col&lt;/span&gt;&lt;span class=&quot;o&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;lineno&quot;&gt;34 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from_rows&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;titles_from_data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C6&amp;quot;&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;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;line_chart.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s the outcome of the above piece of code:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_21.06.42.e4e52ab1b433.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/Screenshot_2019-06-24_21.06.42.e4e52ab1b433.png&quot; width=&quot;2160&quot; height=&quot;1414&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.06.42.e4e52ab1b433.png&amp;amp;w=540&amp;amp;sig=362319a9716ded57c9567de98c52a4dc805b5346 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.06.42.e4e52ab1b433.png&amp;amp;w=1080&amp;amp;sig=cbd7b37aa77318e4ed8d2401281817fb53a7144b 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_21.06.42.e4e52ab1b433.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Line Chart&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One thing to keep in mind here is the fact that you&amp;rsquo;re using &lt;code&gt;from_rows=True&lt;/code&gt; when adding the data. This argument makes the chart plot row by row instead of column by column.&lt;/p&gt;
&lt;p&gt;In your sample data, you see that each product has a row with 12 values (1 column per month). That&amp;rsquo;s why you use &lt;code&gt;from_rows&lt;/code&gt;. If you don&amp;rsquo;t pass that argument, by default, the chart tries to plot by column, and you&amp;rsquo;ll get a month-by-month comparison of sales.&lt;/p&gt;
&lt;p&gt;Another difference that has to do with the above argument change is the fact that our &lt;code&gt;Reference&lt;/code&gt; now starts from the first column, &lt;code&gt;min_col=1&lt;/code&gt;, instead of the second one. This change is needed because the chart now expects the first column to have the titles.&lt;/p&gt;
&lt;p&gt;There are a couple of other things you can also change regarding the style of the chart. For example, you can add specific categories to the chart:&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;cats&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worksheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;min_row&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;max_row&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;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;max_col&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_categories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add this piece of code before saving the workbook, and you should see the month names appearing instead of numbers:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_21.08.05.8867e2cced85.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/Screenshot_2019-06-24_21.08.05.8867e2cced85.png&quot; width=&quot;2160&quot; height=&quot;1414&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.08.05.8867e2cced85.png&amp;amp;w=540&amp;amp;sig=6e48719b75e585dcb58fec3768def0630bb367ff 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.08.05.8867e2cced85.png&amp;amp;w=1080&amp;amp;sig=9fed1350289fe067d8f50c07516bfcc460f4a720 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_21.08.05.8867e2cced85.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Line Chart and Categories&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Code-wise, this is a minimal change. But in terms of the readability of the spreadsheet, this makes it much easier for someone to open the spreadsheet and understand the chart straight away.&lt;/p&gt;
&lt;p&gt;Another thing you can do to improve the chart readability is to add an axis. You can do it using the attributes &lt;code&gt;x_axis&lt;/code&gt; and &lt;code&gt;y_axis&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;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Months&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Sales (per unit)&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will generate a spreadsheet like the below one:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_21.09.46.ce55f629b073.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/Screenshot_2019-06-24_21.09.46.ce55f629b073.png&quot; width=&quot;2160&quot; height=&quot;1414&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.09.46.ce55f629b073.png&amp;amp;w=540&amp;amp;sig=ac73f73702b55a957c77d6da224cde46c2c9a802 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.09.46.ce55f629b073.png&amp;amp;w=1080&amp;amp;sig=408f6929a900e4a5ccb5cb1cca8647cf64d0d069 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_21.09.46.ce55f629b073.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Line Chart, Categories and Axis Titles&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, small changes like the above make reading your chart a much easier and quicker task.&lt;/p&gt;
&lt;p&gt;There is also a way to style your chart by using Excel&amp;rsquo;s default &lt;code&gt;ChartStyle&lt;/code&gt; property. In this case, you have to choose a number between 1 and 48. Depending on your choice, the colors of your chart change as well:&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;# You can play with this by choosing any number between 1 and 48&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the style selected above, all lines have some shade of orange:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_21.16.31.7df18bbe94cb.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/Screenshot_2019-06-24_21.16.31.7df18bbe94cb.png&quot; width=&quot;2160&quot; height=&quot;1414&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.16.31.7df18bbe94cb.png&amp;amp;w=540&amp;amp;sig=4b0439c6c48d0b3f96f411e6198f6fd49d5c7026 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.16.31.7df18bbe94cb.png&amp;amp;w=1080&amp;amp;sig=4d0aad0a27321bb321dc9c88158f357155968121 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_21.16.31.7df18bbe94cb.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Line Chart, Categories, Axis Titles and Style&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is no clear documentation on what each style number looks like, but &lt;a href=&quot;https://1drv.ms/x/s!Asf0Y5Y4GI3Mg6kZNRd1IA09NLWv9A&quot;&gt;this spreadsheet&lt;/a&gt; has a few examples of the styles available.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card0fb191&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;#collapse0fb191&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse0fb191&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;#collapse0fb191&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse0fb191&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse0fb191&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card0fb191&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;Here&amp;rsquo;s the full code used to generate the line chart with categories, axis titles, and style:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl.chart&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LineChart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Let&amp;#39;s create some sample sales data&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt; &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;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;January&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;February&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;March&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;April&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;May&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;June&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;July&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;August&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;September&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;s2&quot;&gt;&amp;quot;October&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;November&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;December&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;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;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;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;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sheet&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;row&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;max_row&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;n&quot;&gt;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;max_col&lt;/span&gt;&lt;span class=&quot;o&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&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;cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;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;randrange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a LineChart and add the main data&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LineChart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worksheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;max_row&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;n&quot;&gt;min_col&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;max_col&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;titles_from_data&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;from_rows&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Add categories to the chart&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cats&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worksheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;min_row&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;max_row&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;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;max_col&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_categories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Rename the X and Y Axis&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Months&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Sales (per unit)&amp;quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Apply a specific Style&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Save!&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C6&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;line_chart.xlsx&amp;quot;&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;There are a lot more chart types and customization you can apply, so be sure to check out the &lt;a href=&quot;https://openpyxl.readthedocs.io/en/stable/charts/introduction.html&quot;&gt;package documentation&lt;/a&gt; on this if you need some specific formatting.&lt;/p&gt;
&lt;h3 id=&quot;convert-python-classes-to-excel-spreadsheet&quot;&gt;Convert Python Classes to Excel Spreadsheet&lt;/h3&gt;
&lt;p&gt;You already saw how to convert an Excel spreadsheet&amp;rsquo;s data into Python classes, but now let&amp;rsquo;s do the opposite.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s imagine you have a database and are using some Object-Relational Mapping (ORM) to map DB objects into Python classes. Now, you want to export those same objects into a spreadsheet.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s assume the following &lt;a href=&quot;https://realpython.com/python-data-classes/&quot;&gt;data classes&lt;/a&gt; to represent the data coming from your database regarding product sales:&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;dataclasses&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataclass&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;List&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@dataclass&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;quantity&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;nd&quot;&gt;@dataclass&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&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;n&quot;&gt;sales&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, let&amp;rsquo;s generate some random data, assuming the above classes are stored in a &lt;code&gt;db_classes.py&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &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;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;# Ignore these for now. You&amp;#39;ll use them in a sec ;)&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;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl.chart&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LineChart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&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;db_classes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Sale&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;products&lt;/span&gt; &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;10 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Let&amp;#39;s create 5 products&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&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;sales&lt;/span&gt; &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;14 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Create 5 months of sales&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &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;5&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;sale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Sale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quantity&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;randrange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&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;sales&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;sale&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;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&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;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Product &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;n&quot;&gt;idx&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;sales&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sales&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;products&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;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By running this piece of code, you should get 5 products with 5 months of sales with a random quantity of sales for each month.&lt;/p&gt;
&lt;p&gt;Now, to convert this into a spreadsheet, you need to iterate over the data and append it to the spreadsheet:&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;25 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&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;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&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;c1&quot;&gt;# Append column names first&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&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;s2&quot;&gt;&amp;quot;Product ID&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Product Name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Month 1&amp;quot;&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;s2&quot;&gt;&amp;quot;Month 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;Month 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;Month 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;Month 5&amp;quot;&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;lineno&quot;&gt;32 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Append the data&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;products&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;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;product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sale&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sales&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;data&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;sale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quantity&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;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s it. That should allow you to create a spreadsheet with some data coming from your database.&lt;/p&gt;
&lt;p&gt;However, why not use some of that cool knowledge you gained recently to add a chart as well to display that data more visually?&lt;/p&gt;
&lt;p&gt;All right, then you could probably 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;lineno&quot;&gt;38 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LineChart&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;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worksheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&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;min_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;41 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;max_row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;42 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;min_col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;43 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;max_col&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;p&quot;&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;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;titles_from_data&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;from_rows&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;46 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;B8&amp;quot;&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;lineno&quot;&gt;48 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cats&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worksheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sheet&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;n&quot;&gt;min_row&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;lineno&quot;&gt;50 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;max_row&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;lineno&quot;&gt;51 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;min_col&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;lineno&quot;&gt;52 &lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;max_col&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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;53 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_categories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cats&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;lineno&quot;&gt;55 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Months&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;56 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Sales (per unit)&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;57 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;58 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;oop_sample.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we&amp;rsquo;re talking! Here&amp;rsquo;s a spreadsheet generated from database objects and with a chart and everything:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_21.26.23.1f355e76586d.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/Screenshot_2019-06-24_21.26.23.1f355e76586d.png&quot; width=&quot;2160&quot; height=&quot;1414&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.26.23.1f355e76586d.png&amp;amp;w=540&amp;amp;sig=135f4ee5413467c91f65bbb6e914724cdf1fd413 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.26.23.1f355e76586d.png&amp;amp;w=1080&amp;amp;sig=5b7dd165f92c237ddd049350ca6fc6a165e10512 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_21.26.23.1f355e76586d.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Conversion from Python Data Classes&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s a great way for you to wrap up your new knowledge of charts!&lt;/p&gt;
&lt;h3 id=&quot;bonus-working-with-pandas&quot;&gt;Bonus: Working With Pandas&lt;/h3&gt;
&lt;p&gt;Even though you can use &lt;a href=&quot;https://realpython.com/working-with-large-excel-files-in-pandas/&quot;&gt;Pandas to handle Excel files&lt;/a&gt;, there are few things that you either can&amp;rsquo;t accomplish with Pandas or that you&amp;rsquo;d be better off just using &lt;code&gt;openpyxl&lt;/code&gt; directly.&lt;/p&gt;
&lt;p&gt;For example, some of the advantages of using &lt;code&gt;openpyxl&lt;/code&gt; are the ability to easily customize your spreadsheet with styles, conditional formatting, and such.&lt;/p&gt;
&lt;p&gt;But guess what, you don&amp;rsquo;t have to worry about picking. In fact, &lt;code&gt;openpyxl&lt;/code&gt; has support for both converting data from a Pandas DataFrame into a workbook or the opposite, converting an &lt;code&gt;openpyxl&lt;/code&gt; workbook into a Pandas DataFrame.&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;re new to Pandas, check our &lt;a href=&quot;https://realpython.com/courses/pandas-dataframes-101/&quot;&gt;course on Pandas DataFrames&lt;/a&gt; beforehand.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;First things first, remember to install the &lt;code&gt;pandas&lt;/code&gt; package:&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 pandas
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, let&amp;rsquo;s create a sample DataFrame:&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;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pd&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;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;lineno&quot;&gt; 4 &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Product Name&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;Product 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;Product 2&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;s2&quot;&gt;&amp;quot;Sales Month 1&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;mi&quot;&gt;20&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;s2&quot;&gt;&amp;quot;Sales Month 2&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;mi&quot;&gt;35&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;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that you have some data, you can use &lt;code&gt;.dataframe_to_rows()&lt;/code&gt; to convert it from a DataFrame into a worksheet:&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;10 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&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;openpyxl.utils.dataframe&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataframe_to_rows&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;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Workbook&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;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&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;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;dataframe_to_rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&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;header&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sheet&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;row&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;lineno&quot;&gt;19 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pandas.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should see a spreadsheet that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screenshot_2019-06-24_21.42.15.0a4208db25f0.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/Screenshot_2019-06-24_21.42.15.0a4208db25f0.png&quot; width=&quot;2160&quot; height=&quot;1414&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.42.15.0a4208db25f0.png&amp;amp;w=540&amp;amp;sig=636303dd8f99512651c5868f4ef572b2afa75d3c 540w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screenshot_2019-06-24_21.42.15.0a4208db25f0.png&amp;amp;w=1080&amp;amp;sig=c2ddf015c46566fc545ad03187cc5780a61938f9 1080w, https://files.realpython.com/media/Screenshot_2019-06-24_21.42.15.0a4208db25f0.png 2160w&quot; sizes=&quot;75vw&quot; alt=&quot;Example Spreadsheet With Data from Pandas Data Frame&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to add the &lt;a href=&quot;https://realpython.com/python-data-cleaning-numpy-pandas/#changing-the-index-of-a-dataframe&quot;&gt;DataFrame&amp;rsquo;s index&lt;/a&gt;, you can change &lt;code&gt;index=True&lt;/code&gt;, and it adds each row&amp;rsquo;s index into your spreadsheet.&lt;/p&gt;
&lt;p&gt;On the other hand, if you want to convert a spreadsheet into a DataFrame, you can also do it in a very straightforward way like so:&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;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, if you want to add the correct headers and use the review ID as the index, for example, then you can also do it like this instead:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;openpyxl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;mapping&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REVIEW_ID&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_workbook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sample.xlsx&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workbook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set the first row as the columns for the DataFrame&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cols&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set the field &amp;quot;review_id&amp;quot; as the indexes for each row&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REVIEW_ID&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;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&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;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using indexes and columns allows you to access data from your DataFrame easily:&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;df&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Index([&amp;#39;marketplace&amp;#39;, &amp;#39;customer_id&amp;#39;, &amp;#39;review_id&amp;#39;, &amp;#39;product_id&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       &amp;#39;product_parent&amp;#39;, &amp;#39;product_title&amp;#39;, &amp;#39;product_category&amp;#39;, &amp;#39;star_rating&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       &amp;#39;helpful_votes&amp;#39;, &amp;#39;total_votes&amp;#39;, &amp;#39;vine&amp;#39;, &amp;#39;verified_purchase&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       &amp;#39;review_headline&amp;#39;, &amp;#39;review_body&amp;#39;, &amp;#39;review_date&amp;#39;],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;      dtype=&amp;#39;object&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Get first 10 reviews&amp;#39; star rating&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;star_rating&amp;quot;&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;R3O9SGZBVQBV76    5&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;RKH8BNC3L5DLF     5&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;R2HLE8WKZSU3NL    2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;R31U3UH5AZ42LL    5&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;R2SV659OUJ945Y    4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;RA51CP8TR5A2L     5&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;RB2Q7DLDN6TH6     5&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;R2RHFJV0UYBK3Y    1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;R2Z6JOQ94LFHEP    5&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;RX27XIIWY5JPB     4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Name: star_rating, dtype: int64&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;# Grab review with id &amp;quot;R2EQL1V1L6E0C9&amp;quot;, using the index&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;R2EQL1V1L6E0C9&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;marketplace               US&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;customer_id         15305006&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;review_id     R2EQL1V1L6E0C9&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;product_id        B004LURNO6&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;product_parent     892860326&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;review_headline   Five Stars&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;review_body          Love it&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;review_date       2015-08-31&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Name: R2EQL1V1L6E0C9, dtype: object&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There you go, whether you want to use &lt;code&gt;openpyxl&lt;/code&gt; to prettify your Pandas dataset or use Pandas to do some hardcore algebra, you now know how to switch between both packages.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Phew&lt;/em&gt;, after that long read, you now know how to work with spreadsheets in Python! You can rely on &lt;code&gt;openpyxl&lt;/code&gt;, your trustworthy companion, to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extract valuable information from spreadsheets in a Pythonic manner&lt;/li&gt;
&lt;li&gt;Create your own spreadsheets, no matter the complexity level&lt;/li&gt;
&lt;li&gt;Add cool features such as conditional formatting or charts to your spreadsheets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a few other things you can do with &lt;code&gt;openpyxl&lt;/code&gt; that might not have been covered in this tutorial, but you can always check the package&amp;rsquo;s official &lt;a href=&quot;https://openpyxl.readthedocs.io/en/stable/index.html&quot;&gt;documentation website&lt;/a&gt; to learn more about it. You can even venture into checking its &lt;a href=&quot;https://bitbucket.org/openpyxl/openpyxl/src/default/&quot;&gt;source code&lt;/a&gt; and improving the package further.&lt;/p&gt;
&lt;p&gt;Feel free to leave any comments below if you have any questions, or if there&amp;rsquo;s any section you&amp;rsquo;d love to hear more about.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Dataset:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/optins/view/openpyxl-sample-dataset/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-openpyxl-sample-dataset&quot; data-focus=&quot;false&quot;&gt;Click here to download the dataset for the openpyxl exercise you&#39;ll be following in this tutorial.&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Your Guide to the CPython Source Code</title>
      <id>https://realpython.com/cpython-source-code-guide/</id>
      <link href="https://realpython.com/cpython-source-code-guide/"/>
      <updated>2019-08-21T16:10:00+00:00</updated>
      <summary>In this detailed Python tutorial, you&#39;ll explore the CPython source code. By following this step-by-step walkthrough, you&#39;ll take a deep dive into how the CPython compiler works and how your Python code gets executed.</summary>
      <content type="html">
        &lt;p&gt;Are there certain parts of Python that just seem magic? Like how are dictionaries so much faster than looping over a list to find an item. How does a generator remember the state of the variables each time it yields a value and why do you never have to allocate memory like other languages? It turns out, CPython, the most popular Python runtime is written in human-readable C and Python code. This tutorial will walk you through the CPython source code. &lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll cover all the concepts behind the internals of CPython, how they work and visual explanations as you go.&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;Read and navigate the source code&lt;/li&gt;
&lt;li&gt;Compile CPython from source code&lt;/li&gt;
&lt;li&gt;Navigate and comprehend the inner workings of concepts like lists, dictionaries, and generators&lt;/li&gt;
&lt;li&gt;Run the test suite&lt;/li&gt;
&lt;li&gt;Modify or upgrade components of the CPython library to contribute them to future versions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yes, this is a very long article. If you just made yourself a fresh cup of tea, coffee or your favorite beverage, it&amp;rsquo;s going to be cold by the end of Part 1. &lt;/p&gt;
&lt;p&gt;This tutorial is split into five parts. Take your time for each part and make sure you try out the demos and the interactive components. You can feel a sense of achievement that you grasp the core concepts of Python that can make you a better Python programmer.&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 h1=&quot;h1&quot; id=&quot;part-1-introduction-to-cpython&quot;&gt;Part 1: Introduction to CPython&lt;/h2&gt;
&lt;p&gt;When you type &lt;code&gt;python&lt;/code&gt; at the console or install a Python distribution from &lt;a href=&quot;https://www.python.org&quot;&gt;python.org&lt;/a&gt;, you are running &lt;strong&gt;CPython&lt;/strong&gt;. CPython is one of the many Python runtimes, maintained and written by different teams of developers. Some other runtimes you may have heard are &lt;a href=&quot;https://pypy.org/&quot;&gt;PyPy&lt;/a&gt;, &lt;a href=&quot;https://cython.org/&quot;&gt;Cython&lt;/a&gt;, and &lt;a href=&quot;https://www.jython.org/&quot;&gt;Jython&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The unique thing about CPython is that it contains both a runtime and the shared language specification that all Python runtimes use. CPython is the &amp;ldquo;official,&amp;rdquo; or reference implementation of Python.&lt;/p&gt;
&lt;p&gt;The Python language specification is the document that the description of the Python language. For example, it says that &lt;code&gt;assert&lt;/code&gt; is a reserved keyword, and that &lt;code&gt;[]&lt;/code&gt; is used for indexing, slicing, and creating empty lists.&lt;/p&gt;
&lt;p&gt;Think about what you expect to be inside the Python distribution on your computer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When you type &lt;code&gt;python&lt;/code&gt; without a file or module, it gives an interactive prompt.&lt;/li&gt;
&lt;li&gt;You can import built-in modules from the standard library like &lt;code&gt;json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can install packages from the internet using &lt;code&gt;pip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can test your applications using the built-in &lt;code&gt;unittest&lt;/code&gt; library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are all part of the CPython distribution. There&amp;rsquo;s a lot more than just a compiler.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article is written against version &lt;a href=&quot;https://github.com/python/cpython/tree/v3.8.0b4&quot;&gt;3.8.0b4&lt;/a&gt; of the CPython source code.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;whats-in-the-source-code&quot;&gt;What&amp;rsquo;s in the Source Code?&lt;/h3&gt;
&lt;p&gt;The CPython source distribution comes with a whole range of tools, libraries, and components. We&amp;rsquo;ll explore those in this article. First we are going to focus on the compiler.&lt;/p&gt;
&lt;p&gt;To download a copy of the CPython source code, you can use &lt;code&gt;git&lt;/code&gt; to pull the latest version to a working copy locally:&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;git clone https://github.com/python/cpython&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;cd cpython&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;git checkout v3.8.0b4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you don&amp;rsquo;t have Git available, you can download the source in a &lt;a href=&quot;https://github.com/python/cpython/archive/v3.8.0b4.zip&quot;&gt;ZIP&lt;/a&gt; file directly from the GitHub website.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Inside of the newly downloaded &lt;code&gt;cpython&lt;/code&gt; directory, you will find the following subdirectories:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;cpython/
│
├── Doc      ← Source for the documentation
├── Grammar  ← The computer-readable language definition
├── Include  ← The C header files
├── Lib      ← Standard library modules written in Python
├── Mac      ← macOS support files
├── Misc     ← Miscellaneous files
├── Modules  ← Standard Library Modules written in C
├── Objects  ← Core types and the object model
├── Parser   ← The Python parser source code
├── PC       ← Windows build support files
├── PCbuild  ← Windows build support files for older Windows versions
├── Programs ← Source code for the python executable and other binaries
├── Python   ← The CPython interpreter source code
└── Tools    ← Standalone tools useful for building or extending Python
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, we&amp;rsquo;ll compile CPython from the source code. This step requires a C compiler, and some build tools, which depend on the operating system you&amp;rsquo;re using.&lt;/p&gt;
&lt;h3 id=&quot;compiling-cpython-macos&quot;&gt;Compiling CPython (macOS)&lt;/h3&gt;
&lt;p&gt;Compiling CPython on macOS is straightforward. You will first need the essential C compiler toolkit. The Command Line Development Tools is an app that you can update in macOS through the App Store. You need to perform the initial installation on the terminal.&lt;/p&gt;
&lt;p&gt;To open up a terminal in macOS, go to the Launchpad, then &lt;em&gt;Other&lt;/em&gt; then choose the &lt;em&gt;Terminal&lt;/em&gt; app. You will want to save this app to your Dock, so right-click the Icon and select &lt;em&gt;Keep in Dock&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Now, within the terminal, install the C compiler and toolkit by running 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;gp&quot;&gt;$&lt;/span&gt; xcode-select --install
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command will pop up with a prompt to download and install a set of tools, including Git, Make, and the GNU C compiler.&lt;/p&gt;
&lt;p&gt;You will also need a working copy of &lt;a href=&quot;https://www.openssl.org/&quot;&gt;OpenSSL&lt;/a&gt; to use for fetching packages from the PyPi.org website. If you later plan on using this build to install additional packages, SSL validation is required.&lt;/p&gt;
&lt;p&gt;The simplest way to install OpenSSL on macOS is by using &lt;a href=&quot;https://brew.sh&quot;&gt;HomeBrew&lt;/a&gt;. If you already have HomeBrew installed, you can install the dependencies for CPython with the &lt;code&gt;brew install&lt;/code&gt; 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 openssl xz zlib
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that you have the dependencies, you can run the &lt;code&gt;configure&lt;/code&gt; script, enabling SSL support by discovering the location that HomeBrew installed to and enabling the debug hooks &lt;code&gt;--with-pydebug&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CPPFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;-I&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;brew --prefix zlib&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/include&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;LDFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;-L&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;brew --prefix zlib&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/lib&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 ./configure --with-openssl&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;brew --prefix openssl&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt; --with-pydebug
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will generate a &lt;code&gt;Makefile&lt;/code&gt; in the root of the repository that you can use to automate the build process. The &lt;code&gt;./configure&lt;/code&gt; step only needs to be run once. You can build the CPython binary by running:&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; make -j2 -s
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;-j2&lt;/code&gt; flag allows &lt;code&gt;make&lt;/code&gt; to run 2 jobs simultaneously. If you have 4 cores, you can change this to 4. The &lt;code&gt;-s&lt;/code&gt; flag stops the &lt;code&gt;Makefile&lt;/code&gt; from printing every command it runs to the console. You can remove this, but the output is very verbose.&lt;/p&gt;
&lt;p&gt;During the build, you may receive some errors, and in the summary, it will notify you that not all packages could be built. For example, &lt;code&gt;_dbm&lt;/code&gt;, &lt;code&gt;_sqlite3&lt;/code&gt;, &lt;code&gt;_uuid&lt;/code&gt;, &lt;code&gt;nis&lt;/code&gt;, &lt;code&gt;ossaudiodev&lt;/code&gt;, &lt;code&gt;spwd&lt;/code&gt;, and &lt;code&gt;_tkinter&lt;/code&gt; would fail to build with this set of instructions. That&amp;rsquo;s okay if you aren&amp;rsquo;t planning on developing against those packages. If you are, then check out the &lt;a href=&quot;https://devguide.python.org/&quot;&gt;dev guide&lt;/a&gt; website for more information.&lt;/p&gt;
&lt;p&gt;The build will take a few minutes and generate a binary called &lt;code&gt;python.exe&lt;/code&gt;.  Every time you make changes to the source code, you will need to re-run &lt;code&gt;make&lt;/code&gt; with the same flags.
The &lt;code&gt;python.exe&lt;/code&gt; binary is the debug binary of CPython. Execute &lt;code&gt;python.exe&lt;/code&gt; to see a working REPL:&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.exe
&lt;span class=&quot;go&quot;&gt;Python 3.8.0b4 (tags/v3.8.0b4:d93605de72, Aug 30 2019, 10:00:03) &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[Clang 10.0.1 (clang-1001.0.46.4)] on darwin&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&lt;/span&gt;&amp;gt;&amp;gt; 
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; 
Yes, that&amp;rsquo;s right, the macOS build has a file extension for &lt;code&gt;.exe&lt;/code&gt;. This is &lt;em&gt;not&lt;/em&gt; because it&amp;rsquo;s a Windows binary. Because macOS has a case-insensitive filesystem and when working with the binary, the developers didn&amp;rsquo;t want people to accidentally refer to the directory &lt;code&gt;Python/&lt;/code&gt; so &lt;code&gt;.exe&lt;/code&gt; was appended to avoid ambiguity.
If you later run &lt;code&gt;make install&lt;/code&gt; or &lt;code&gt;make altinstall&lt;/code&gt;, it will rename the file back to &lt;code&gt;python&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;compiling-cpython-linux&quot;&gt;Compiling CPython (Linux)&lt;/h3&gt;
&lt;p&gt;For Linux, the first step is to download and install &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;gcc&lt;/code&gt;, &lt;code&gt;configure&lt;/code&gt;, and &lt;code&gt;pkgconfig&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;For Fedora Core, RHEL, CentOS, or other yum-based systems: &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 yum install yum-utils
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For Debian, Ubuntu, or other &lt;code&gt;apt&lt;/code&gt;-based systems:&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 build-essential
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then install the required packages, for Fedora Core, RHEL, CentOS or other yum-based systems: &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 yum-builddep python3
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For Debian, Ubuntu, or other &lt;code&gt;apt&lt;/code&gt;-based systems:&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 libssl-dev zlib1g-dev libncurses5-dev &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev libffi-dev
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that you have the dependencies, you can run the &lt;code&gt;configure&lt;/code&gt; script, enabling the debug hooks &lt;code&gt;--with-pydebug&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; ./configure --with-pydebug
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Review the output to ensure that OpenSSL support was marked as &lt;code&gt;YES&lt;/code&gt;. Otherwise, check with your distribution for instructions on installing the headers for OpenSSL.&lt;/p&gt;
&lt;p&gt;Next, you can build the CPython binary by running the generated &lt;code&gt;Makefile&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; make -j2 -s
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;During the build, you may receive some errors, and in the summary, it will notify you that not all packages could be built. That&amp;rsquo;s okay if you aren&amp;rsquo;t planning on developing against those packages. If you are, then check out the &lt;a href=&quot;https://devguide.python.org/&quot;&gt;dev guide&lt;/a&gt; website for more information.&lt;/p&gt;
&lt;p&gt;The build will take a few minutes and generate a binary called &lt;code&gt;python&lt;/code&gt;. This is the debug binary of CPython. Execute &lt;code&gt;./python&lt;/code&gt; to see a working REPL:&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
&lt;span class=&quot;go&quot;&gt;Python 3.8.0b4 (tags/v3.8.0b4:d93605de72, Aug 30 2019, 10:00:03) &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[Clang 10.0.1 (clang-1001.0.46.4)] on darwin&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&lt;/span&gt;&amp;gt;&amp;gt; 
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;compiling-cpython-windows&quot;&gt;Compiling CPython (Windows)&lt;/h3&gt;
&lt;p&gt;Inside the PC folder is a Visual Studio project file for building and exploring CPython. To use this, you need to have Visual Studio installed on your PC.&lt;/p&gt;
&lt;p&gt;The newest version of Visual Studio, Visual Studio 2019, makes it easier to work with Python and the CPython source code, so it is recommended for use in this tutorial. If you already have Visual Studio 2017 installed, that would also work fine.&lt;/p&gt;
&lt;p&gt;None of the paid features are required for compiling CPython or this tutorial. You can use the Community edition of Visual Studio, which is available for free from &lt;a href=&quot;https://visualstudio.microsoft.com/vs/&quot;&gt;Microsoft&amp;rsquo;s Visual Studio website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve downloaded the installer, you&amp;rsquo;ll be asked to select which components you want to install. The bare minimum for this tutorial is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Python Development&lt;/strong&gt; workload&lt;/li&gt;
&lt;li&gt;The optional &lt;strong&gt;Python native development tools&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Python 3 64-bit (3.7.2) (can be deselected if you already have Python 3.7 installed)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any other optional features can be deselected if you want to be more conscientious with disk space:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-08-22_at_2.47.23_pm.5e8682a89503.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/Screen_Shot_2019-08-22_at_2.47.23_pm.5e8682a89503.png&quot; width=&quot;2504&quot; height=&quot;1260&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-08-22_at_2.47.23_pm.5e8682a89503.png&amp;amp;w=626&amp;amp;sig=86eb9f82580a69f533983087ba0fa4faf0d5bf96 626w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-08-22_at_2.47.23_pm.5e8682a89503.png&amp;amp;w=1252&amp;amp;sig=fe2157486f81073eabe043b3c441af23dd67b78a 1252w, https://files.realpython.com/media/Screen_Shot_2019-08-22_at_2.47.23_pm.5e8682a89503.png 2504w&quot; sizes=&quot;75vw&quot; alt=&quot;Visual Studio Options Window&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The installer will then download and install all of the required components. The installation could take an hour, so you may want to read on and come back to this section.&lt;/p&gt;
&lt;p&gt;Once the installer has completed, click the &lt;em&gt;Launch&lt;/em&gt; button to start Visual Studio. You will be prompted to sign in. If you have a Microsoft account you can log in, or skip that step.&lt;/p&gt;
&lt;p&gt;Once Visual Studio starts, you will be prompted to Open a Project. A shortcut to getting started with the Git configuration and cloning CPython is to choose the &lt;em&gt;Clone or check out code&lt;/em&gt; option:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Capture3.e19765d74ec4.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/Capture3.e19765d74ec4.PNG&quot; width=&quot;2048&quot; height=&quot;1420&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Capture3.e19765d74ec4.PNG&amp;amp;w=512&amp;amp;sig=e475e2a09cd780894f108850f91736c53ac95f27 512w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Capture3.e19765d74ec4.PNG&amp;amp;w=1024&amp;amp;sig=47d66a316c2546c9787e5af4cb4a9a006dca936d 1024w, https://files.realpython.com/media/Capture3.e19765d74ec4.PNG 2048w&quot; sizes=&quot;75vw&quot; alt=&quot;Choosing a Project Type in Visual Studio&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For the project URL, type &lt;code&gt;https://github.com/python/cpython&lt;/code&gt; to clone:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Capture4.ea01418a971c.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/Capture4.ea01418a971c.PNG&quot; width=&quot;2048&quot; height=&quot;1420&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Capture4.ea01418a971c.PNG&amp;amp;w=512&amp;amp;sig=47ed81b234652446a4f0e77e2a3f70e0074ac222 512w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Capture4.ea01418a971c.PNG&amp;amp;w=1024&amp;amp;sig=de393823fe557847f295d040573bd061b2ccd557 1024w, https://files.realpython.com/media/Capture4.ea01418a971c.PNG 2048w&quot; sizes=&quot;75vw&quot; alt=&quot;Cloning projects in Visual Studio&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Visual Studio will then download a copy of CPython from GitHub using the version of Git bundled with Visual Studio. This step also saves you the hassle of having to install Git on Windows. The download may take 10 minutes.&lt;/p&gt;
&lt;p&gt;Once the project has downloaded, you need to point it to the &lt;strong&gt;&lt;code&gt;pcbuild&lt;/code&gt;&lt;/strong&gt; Solution file, by clicking on &lt;em&gt;Solutions and Projects&lt;/em&gt; and selecting &lt;code&gt;pcbuild.sln&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Capture6.3d06a62b8e87.PNG&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-50&quot; src=&quot;https://files.realpython.com/media/Capture6.3d06a62b8e87.PNG&quot; width=&quot;863&quot; height=&quot;565&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Capture6.3d06a62b8e87.PNG&amp;amp;w=215&amp;amp;sig=0d4c23758a58848ea65b74514aca9e15a72748fa 215w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Capture6.3d06a62b8e87.PNG&amp;amp;w=431&amp;amp;sig=05f0ebe121ef54abf51bcdb55fba695d28656868 431w, https://files.realpython.com/media/Capture6.3d06a62b8e87.PNG 863w&quot; sizes=&quot;75vw&quot; alt=&quot;Selecting a solution&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When the solution is loaded, it will prompt you to retarget the project&amp;rsquo;s inside the solution to the version of the C/C++ compiler you have installed. Visual Studio will also target the version of the Windows SDK you have installed.&lt;/p&gt;
&lt;p&gt;Ensure that you change the Windows SDK version to the newest installed version and the platform toolset to the latest version. If you missed this window, you can right-click on the Solution in the &lt;em&gt;Solutions and Projects&lt;/em&gt; window and click &lt;em&gt;Retarget Solution&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Once this is complete, you need to download some source files to be able to build the whole CPython package. Inside the &lt;code&gt;PCBuild&lt;/code&gt; folder there is a &lt;code&gt;.bat&lt;/code&gt; file that automates this for you. &lt;a href=&quot;https://www.youtube.com/watch?v=bgSSJQolR0E&quot;&gt;Open up a command-line prompt inside&lt;/a&gt; the downloaded &lt;code&gt;PCBuild&lt;/code&gt; and run &lt;code&gt;get_externals.bat&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; &amp;gt; get_externals.bat&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Using py -3.7 (found 3.7 with py.exe)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fetching external libraries...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fetching bzip2-1.0.6...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fetching sqlite-3.21.0.0...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fetching xz-5.2.2...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fetching zlib-1.2.11...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fetching external binaries...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fetching openssl-bin-1.1.0j...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Fetching tcltk-8.6.9.0...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Finished.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, back within Visual Studio, build CPython by 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-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-b&quot;&gt;B&lt;/kbd&gt;&lt;/span&gt;, or choosing &lt;em&gt;Build Solution&lt;/em&gt; from the top menu. If you receive any errors about the Windows SDK being missing, make sure you set the right targeting settings in the &lt;em&gt;Retarget Solution&lt;/em&gt; window. You should also see &lt;em&gt;Windows Kits&lt;/em&gt; inside your Start Menu, and &lt;em&gt;Windows Software Development Kit&lt;/em&gt; inside of that menu.&lt;/p&gt;
&lt;p&gt;The build stage could take 10 minutes or more for the first time. Once the build is completed, you may see a few warnings that you can ignore and eventual completion.&lt;/p&gt;
&lt;p&gt;To start the debug version of CPython, press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-f5&quot;&gt;F5&lt;/kbd&gt;&lt;/span&gt; and CPython will start in Debug mode straight into the REPL:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Capture8.967a3606daf0.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/Capture8.967a3606daf0.PNG&quot; width=&quot;3360&quot; height=&quot;2100&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Capture8.967a3606daf0.PNG&amp;amp;w=840&amp;amp;sig=1822fde8ffe6946fc91e47dd8975aa23add8b23a 840w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Capture8.967a3606daf0.PNG&amp;amp;w=1680&amp;amp;sig=a093e68320ad548384c585840002e4294ab4bf94 1680w, https://files.realpython.com/media/Capture8.967a3606daf0.PNG 3360w&quot; sizes=&quot;75vw&quot; alt=&quot;CPython debugging Windows&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once this is completed, you can run the Release build by changing the build configuration from &lt;em&gt;Debug&lt;/em&gt; to &lt;em&gt;Release&lt;/em&gt; on the top menu bar and rerunning Build Solution again.
You now have both Debug and Release versions of the CPython binary within &lt;code&gt;PCBuild\win32\&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can set up Visual Studio to be able to open a REPL with either the Release or Debug build by choosing &lt;em&gt;&lt;code&gt;Tools&lt;/code&gt;-&amp;gt;&lt;code&gt;Python&lt;/code&gt;-&amp;gt;&lt;code&gt;Python Environments&lt;/code&gt;&lt;/em&gt; from the top menu:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Environments.96a819ecf0b3.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/Environments.96a819ecf0b3.png&quot; width=&quot;3360&quot; height=&quot;2033&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Environments.96a819ecf0b3.png&amp;amp;w=840&amp;amp;sig=f8dd9b3b31d44c25cbe06d56078b0462cb0fa753 840w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Environments.96a819ecf0b3.png&amp;amp;w=1680&amp;amp;sig=e8ca69be87363b62ccda44bcf53bedd4e4e320c2 1680w, https://files.realpython.com/media/Environments.96a819ecf0b3.png 3360w&quot; sizes=&quot;75vw&quot; alt=&quot;Choosing Python environments&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then click &lt;em&gt;Add Environment&lt;/em&gt; and then target the Debug or Release binary. The Debug binary will end in &lt;code&gt;_d.exe&lt;/code&gt;, for example, &lt;code&gt;python_d.exe&lt;/code&gt; and &lt;code&gt;pythonw_d.exe&lt;/code&gt;. You will most likely want to use the debug binary as it comes with Debugging support in Visual Studio and will be useful for this tutorial.&lt;/p&gt;
&lt;p&gt;In the Add Environment window, target the &lt;code&gt;python_d.exe&lt;/code&gt; file as the interpreter inside the &lt;code&gt;PCBuild/win32&lt;/code&gt; and the &lt;code&gt;pythonw_d.exe&lt;/code&gt; as the windowed interpreter:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/environment3.d33858c1f6aa.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/environment3.d33858c1f6aa.PNG&quot; width=&quot;2048&quot; height=&quot;1352&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/environment3.d33858c1f6aa.PNG&amp;amp;w=512&amp;amp;sig=ffc6b359ac60d689f40f98233466cef35354d239 512w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/environment3.d33858c1f6aa.PNG&amp;amp;w=1024&amp;amp;sig=d881ce7ecabc62624fb2a5154102a5be2ff6a4db 1024w, https://files.realpython.com/media/environment3.d33858c1f6aa.PNG 2048w&quot; sizes=&quot;75vw&quot; alt=&quot;Adding an environment in VS2019&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, you can start a REPL session by clicking &lt;em&gt;Open Interactive Window&lt;/em&gt; in the Python Environments window and you will see the REPL for the compiled version of Python:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/environment4.7c9eade3b74e.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/environment4.7c9eade3b74e.PNG&quot; width=&quot;3360&quot; height=&quot;2033&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/environment4.7c9eade3b74e.PNG&amp;amp;w=840&amp;amp;sig=9e384e72bcfdebb39fe6dc23f21c239a0895ad51 840w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/environment4.7c9eade3b74e.PNG&amp;amp;w=1680&amp;amp;sig=be56aac5b9baffc9b8b0de4701527954ed32ef53 1680w, https://files.realpython.com/media/environment4.7c9eade3b74e.PNG 3360w&quot; sizes=&quot;75vw&quot; alt=&quot;Python Environment REPL&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;During this tutorial there will be REPL sessions with example commands. I encourage you to use the Debug binary to run these REPL sessions in case you want to put in any breakpoints within the code.&lt;/p&gt;
&lt;p&gt;Lastly, to make it easier to navigate the code, in the Solution View, click on the toggle button next to the Home icon to switch to Folder view:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/environments5.6462694398e3.6fb872a5f57d.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/environments5.6462694398e3.6fb872a5f57d.png&quot; width=&quot;1231&quot; height=&quot;692&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/environments5.6462694398e3.6fb872a5f57d.png&amp;amp;w=307&amp;amp;sig=14bf2b50bd86dfabedc3ee1ec75a60ebccd574c4 307w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/environments5.6462694398e3.6fb872a5f57d.png&amp;amp;w=615&amp;amp;sig=0d5644853d8c429ccc78fc1bced16d8f571f555d 615w, https://files.realpython.com/media/environments5.6462694398e3.6fb872a5f57d.png 1231w&quot; sizes=&quot;75vw&quot; alt=&quot;Switching Environment Mode&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now you have a version of CPython compiled and ready to go, let&amp;rsquo;s find out how the CPython compiler works.&lt;/p&gt;
&lt;h3 id=&quot;what-does-a-compiler-do&quot;&gt;What Does a Compiler Do?&lt;/h3&gt;
&lt;p&gt;The purpose of a compiler is to convert one language into another. Think of a compiler like a translator. You would hire a translator to listen to you speaking in English and then speak in Japanese:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/t.38be306a7e83.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/t.38be306a7e83.png&quot; width=&quot;960&quot; height=&quot;540&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/t.38be306a7e83.png&amp;amp;w=240&amp;amp;sig=2ad6eec49af1eaba79b83c099925e01a970d5efd 240w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/t.38be306a7e83.png&amp;amp;w=480&amp;amp;sig=033587107c8dceca7bcc292527a4c815fffb0b8d 480w, https://files.realpython.com/media/t.38be306a7e83.png 960w&quot; sizes=&quot;75vw&quot; alt=&quot;Translating from English to Japanese&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some compilers will compile into a low-level machine code which can be executed directly on a system. Other compilers will compile into an intermediary language, to be executed by a virtual machine.&lt;/p&gt;
&lt;p&gt;One important decision to make when choosing a compiler is the system portability requirements. &lt;a href=&quot;https://en.wikipedia.org/wiki/Java_bytecode&quot;&gt;Java&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Common_Language_Runtime&quot;&gt;.NET CLR&lt;/a&gt; will compile into an Intermediary Language so that the compiled code is portable across multiple systems architectures. C, Go, C++, and Pascal will compile into a low-level executable that will only work on systems similar to the one it was compiled. &lt;/p&gt;
&lt;p&gt;Because Python applications are typically distributed as source code, the role of the Python runtime is to convert the Python source code and execute it in one step. Internally, the CPython runtime does compile your code. A popular misconception is that Python is an interpreted language. It is actually compiled.&lt;/p&gt;
&lt;p&gt;Python code is not compiled into machine-code. It is compiled into a special low-level intermediary language called &lt;strong&gt;bytecode&lt;/strong&gt; that only CPython understands. This code is stored in &lt;code&gt;.pyc&lt;/code&gt; files in a hidden directory and cached for execution. If you run the same Python application twice without changing the source code, it&amp;rsquo;ll always be much faster the second time. This is because it loads the compiled bytecode and executes it directly.&lt;/p&gt;
&lt;h3 id=&quot;why-is-cpython-written-in-c-and-not-python&quot;&gt;Why Is CPython Written in C and Not Python?&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;C&lt;/strong&gt; in CPython is a reference to the C programming language, implying that this Python distribution is written in the C language.&lt;/p&gt;
&lt;p&gt;This statement is largely true: the compiler in CPython is written in pure C. However, many of the standard library modules are written in pure Python or a combination of C and Python.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So why is CPython written in C and not Python?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The answer is located in how compilers work. There are two types of compiler:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Self-hosting&quot;&gt;Self-hosted compilers&lt;/a&gt;&lt;/strong&gt; are compilers written in the language they compile, such as the Go compiler.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Source-to-source_compiler&quot;&gt;Source-to-source compilers&lt;/a&gt;&lt;/strong&gt; are compilers written in another language that already have a compiler.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you&amp;rsquo;re writing a new programming language from scratch, you need an executable application to compile your compiler! You need a compiler to execute anything, so when new languages are developed, they&amp;rsquo;re often written first in an older, more established language.&lt;/p&gt;
&lt;p&gt;A good example would be the Go programming language. The first Go compiler was written in C, then once Go could be compiled, the compiler was rewritten in Go. &lt;/p&gt;
&lt;p&gt;CPython kept its C heritage: many of the standard library modules, like the &lt;code&gt;ssl&lt;/code&gt; module or the &lt;code&gt;sockets&lt;/code&gt; module, are written in C to access low-level operating system APIs.
The APIs in the Windows and Linux kernels for &lt;a href=&quot;https://realpython.com/python-sockets/&quot;&gt;creating network sockets&lt;/a&gt;, &lt;a href=&quot;https://realpython.com/working-with-files-in-python/&quot;&gt;working with the filesystem&lt;/a&gt; or &lt;a href=&quot;https://realpython.com/python-gui-with-wxpython/&quot;&gt;interacting with the display&lt;/a&gt; are all written in C. It made sense for Python&amp;rsquo;s extensibility layer to be focused on the C language. Later in this article, we will cover the Python Standard Library and the C modules.&lt;/p&gt;
&lt;p&gt;There is a Python compiler written in Python called &lt;a href=&quot;https://pypy.org/&quot;&gt;PyPy&lt;/a&gt;. PyPy&amp;rsquo;s logo is an &lt;a href=&quot;https://en.wikipedia.org/wiki/Ouroboros&quot;&gt;Ouroboros&lt;/a&gt; to represent the self-hosting nature of the compiler.&lt;/p&gt;
&lt;p&gt;Another example of a cross-compiler for Python is &lt;a href=&quot;https://www.jython.org/&quot;&gt;Jython&lt;/a&gt;. Jython is written in Java and compiles from Python source code into Java bytecode. In the same way that CPython makes it easy to import C libraries and use them from Python, Jython makes it easy to import and reference Java modules and classes.&lt;/p&gt;
&lt;h3 id=&quot;the-python-language-specification&quot;&gt;The Python Language Specification&lt;/h3&gt;
&lt;p&gt;Contained within the CPython source code is the definition of the Python language. This is the reference specification used by all the Python interpreters.&lt;/p&gt;
&lt;p&gt;The specification is in both human-readable and machine-readable format. Inside the documentation is a detailed explanation of the Python language, what is allowed, and how each statement should behave.&lt;/p&gt;
&lt;h4 id=&quot;documentation&quot;&gt;Documentation&lt;/h4&gt;
&lt;p&gt;Located inside the &lt;code&gt;Doc/reference&lt;/code&gt; directory are &lt;a href=&quot;http://docutils.sourceforge.net/rst.html&quot;&gt;reStructuredText&lt;/a&gt; explanations of each of the features in the Python language. This forms the official Python reference guide on &lt;a href=&quot;https://docs.python.org/3/reference/&quot;&gt;docs.python.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Inside the directory are the files you need to understand the whole language, structure, and keywords:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;cpython/Doc/reference
|
├── compound_stmts.rst
├── datamodel.rst
├── executionmodel.rst
├── expressions.rst
├── grammar.rst
├── import.rst
├── index.rst
├── introduction.rst
├── lexical_analysis.rst
├── simple_stmts.rst
└── toplevel_components.rst
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inside &lt;code&gt;compound_stmts.rst&lt;/code&gt;, the documentation for compound statements, you can see a simple example defining the &lt;code&gt;with&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;with&lt;/code&gt; statement can be used in multiple ways in Python, the simplest being the &lt;a href=&quot;https://dbader.org/blog/python-context-managers-and-with-statement&quot;&gt;instantiation of a context-manager&lt;/a&gt; and a nested block of code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can assign the result to a variable using the &lt;code&gt;as&lt;/code&gt; keyword:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also chain context managers together with a comma:&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;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&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;jk&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;Next, we&amp;rsquo;ll explore the computer-readable documentation of the Python language.&lt;/p&gt;
&lt;h4 id=&quot;grammar&quot;&gt;Grammar&lt;/h4&gt;
&lt;p&gt;The documentation contains the human-readable specification of the language, and the machine-readable specification is housed in a single file, &lt;a href=&quot;https://github.com/python/cpython/blob/master/Grammar/Grammar&quot;&gt;&lt;code&gt;Grammar/Grammar&lt;/code&gt;&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;The Grammar file is written in a context-notation called &lt;a href=&quot;https://en.m.wikipedia.org/wiki/Backus%E2%80%93Naur_form&quot;&gt;Backus-Naur Form (BNF)&lt;/a&gt;. BNF is not specific to Python and is often used as the notation for grammars in many other languages.&lt;/p&gt;
&lt;p&gt;The concept of grammatical structure in a programming language is inspired by &lt;a href=&quot;https://en.wikipedia.org/wiki/Syntactic_Structures&quot;&gt;Noam Chomsky&amp;rsquo;s work on Syntactic Structures&lt;/a&gt; in the 1950s!&lt;/p&gt;
&lt;p&gt;Python&amp;rsquo;s grammar file uses the Extended-BNF (EBNF) specification with regular-expression syntax. So, in the grammar file you can use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;*&lt;/code&gt;&lt;/strong&gt; for repetition&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;+&lt;/code&gt;&lt;/strong&gt; for at-least-once repetition&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/strong&gt; for optional parts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;|&lt;/code&gt;&lt;/strong&gt; for alternatives&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;()&lt;/code&gt;&lt;/strong&gt; for grouping&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you search for the &lt;code&gt;with&lt;/code&gt; statement in the grammar file, at around line 80 you&amp;rsquo;ll see the definitions for the &lt;code&gt;with&lt;/code&gt; statement:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;with_stmt: &amp;#39;with&amp;#39; with_item (&amp;#39;,&amp;#39; with_item)*  &amp;#39;:&amp;#39; suite
with_item: test [&amp;#39;as&amp;#39; expr]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Anything in quotes is a string literal, which is how keywords are defined. So the &lt;code&gt;with_stmt&lt;/code&gt; is specified as:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Starting with the word &lt;code&gt;with&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Followed by a &lt;code&gt;with_item&lt;/code&gt;, which is a &lt;code&gt;test&lt;/code&gt; and (optionally), the word &lt;code&gt;as&lt;/code&gt;, and an expression&lt;/li&gt;
&lt;li&gt;Following one or many items, each separated by a comma&lt;/li&gt;
&lt;li&gt;Ending with a &lt;code&gt;:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Followed by a &lt;code&gt;suite&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are references to some other definitions in these two lines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;suite&lt;/code&gt;&lt;/strong&gt; refers to a block of code with one or multiple statements&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;test&lt;/code&gt;&lt;/strong&gt; refers to a simple statement that is evaluated&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;expr&lt;/code&gt;&lt;/strong&gt; refers to a simple expression&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to explore those in detail, the whole of the Python grammar is defined in this single file.&lt;/p&gt;
&lt;p&gt;If you want to see a recent example of how grammar is used, in PEP 572 the &lt;strong&gt;colon equals&lt;/strong&gt; operator was added to the grammar file in &lt;a href=&quot;https://github.com/python/cpython/commit/8f59ee01be3d83d5513a9a3f654a237d77d80d9a#diff-cb0b9d6312c0d67f6d4aa1966766cedd&quot;&gt;this Git commit&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;using-pgen&quot;&gt;Using &lt;code&gt;pgen&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;The grammar file itself is never used by the Python compiler. Instead, a parser table created by a tool called &lt;code&gt;pgen&lt;/code&gt; is used. &lt;code&gt;pgen&lt;/code&gt; reads the grammar file and converts it into a parser table. If you make changes to the grammar file, you must regenerate the parser table and recompile Python.&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;code&gt;pgen&lt;/code&gt; application was rewritten in Python 3.8 from C to &lt;a href=&quot;https://github.com/python/cpython/blob/master/Parser/pgen/pgen.py&quot;&gt;pure Python&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To see &lt;code&gt;pgen&lt;/code&gt; in action, let&amp;rsquo;s change part of the Python grammar. Around line 51 you will see the definition of a &lt;code&gt;pass&lt;/code&gt; statement:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pass_stmt: &amp;#39;pass&amp;#39;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Change that line to accept the keyword &lt;code&gt;&#39;pass&#39;&lt;/code&gt; or &lt;code&gt;&#39;proceed&#39;&lt;/code&gt; as keywords:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;pass_stmt: &amp;#39;pass&amp;#39; | &amp;#39;proceed&amp;#39;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you need to rebuild the grammar files.
On macOS and Linux, run &lt;code&gt;make regen-grammar&lt;/code&gt; to run &lt;code&gt;pgen&lt;/code&gt; over the altered grammar file. For Windows, there is no officially supported way of running &lt;code&gt;pgen&lt;/code&gt;. However, you can clone &lt;a href=&quot;https://github.com/tonybaloney/cpython/tree/pcbuildregen&quot;&gt;my fork&lt;/a&gt; and run &lt;code&gt;build.bat --regen&lt;/code&gt; from within the &lt;code&gt;PCBuild&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;You should see an output similar to this, showing that the new &lt;code&gt;Include/graminit.h&lt;/code&gt; and &lt;code&gt;Python/graminit.c&lt;/code&gt; files have been generated:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# Regenerate Doc/library/token-list.inc from Grammar/Tokens
# using Tools/scripts/generate_token.py
...
python3 ./Tools/scripts/update_file.py ./Include/graminit.h ./Include/graminit.h.new
python3 ./Tools/scripts/update_file.py ./Python/graminit.c ./Python/graminit.c.new
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;pgen&lt;/code&gt; works by converting the EBNF statements into a &lt;a href=&quot;https://en.wikipedia.org/wiki/Nondeterministic_finite_automaton&quot;&gt;Non-deterministic Finite Automaton (NFA)&lt;/a&gt;, which is then turned into a &lt;a href=&quot;https://en.wikipedia.org/wiki/Deterministic_finite_automaton&quot;&gt;Deterministic Finite Automaton (DFA)&lt;/a&gt;.
The DFAs are used by the parser as parsing tables in a special way that&amp;rsquo;s unique to CPython. This technique was &lt;a href=&quot;http://infolab.stanford.edu/~ullman/dragon/slides1.pdf&quot;&gt;formed at Stanford University&lt;/a&gt; and developed in the 1980s, just before the advent of Python.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;With the regenerated parser tables, you need to recompile CPython to see the new syntax. Use the same compilation steps you used earlier for your operating system.&lt;/p&gt;
&lt;p&gt;If the code compiled successfully, you can execute your new CPython binary and start a REPL.&lt;/p&gt;
&lt;p&gt;In the REPL, you can now try defining a function and instead of using the &lt;code&gt;pass&lt;/code&gt; statement, use the &lt;code&gt;proceed&lt;/code&gt; keyword alternative that you compiled into the Python grammar:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Python 3.8.0b4 (tags/v3.8.0b4:d93605de72, Aug 30 2019, 10:00:03) 
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.
&amp;gt;&amp;gt;&amp;gt; def example():
...    proceed
... 
&amp;gt;&amp;gt;&amp;gt; example()
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Well done! You&amp;rsquo;ve changed the CPython syntax and compiled your own version of CPython. Ship it!&lt;/p&gt;
&lt;p&gt;Next, we&amp;rsquo;ll explore tokens and their relationship to grammar.&lt;/p&gt;
&lt;h4 id=&quot;tokens&quot;&gt;Tokens&lt;/h4&gt;
&lt;p&gt;Alongside the grammar file in the &lt;code&gt;Grammar&lt;/code&gt; folder is a &lt;a href=&quot;https://github.com/python/cpython/blob/master/Grammar/Tokens&quot;&gt;&lt;code&gt;Tokens&lt;/code&gt;&lt;/a&gt; file, which contains each of the unique types found as a leaf node in a parse tree. We will cover parser trees in depth later.
Each token also has a name and a generated unique ID. The names are used to make it simpler to refer to in the tokenizer.&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;code&gt;Tokens&lt;/code&gt; file is a new feature in Python 3.8.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For example, the left parenthesis is called &lt;code&gt;LPAR&lt;/code&gt;, and semicolons are called &lt;code&gt;SEMI&lt;/code&gt;. You&amp;rsquo;ll see these tokens later in the article:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;LPAR                    &amp;#39;(&amp;#39;
RPAR                    &amp;#39;)&amp;#39;
LSQB                    &amp;#39;[&amp;#39;
RSQB                    &amp;#39;]&amp;#39;
COLON                   &amp;#39;:&amp;#39;
COMMA                   &amp;#39;,&amp;#39;
SEMI                    &amp;#39;;&amp;#39;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As with the &lt;code&gt;Grammar&lt;/code&gt; file, if you change the &lt;code&gt;Tokens&lt;/code&gt; file, you need to run &lt;code&gt;pgen&lt;/code&gt; again. &lt;/p&gt;
&lt;p&gt;To see tokens in action, you can use the &lt;code&gt;tokenize&lt;/code&gt; module in CPython. Create a simple Python script called &lt;code&gt;test_tokens.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Hello world!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;proceed&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;For the rest of this tutorial, &lt;code&gt;./python.exe&lt;/code&gt; will refer to the compiled version of CPython. However, the actual command will depend on your system.&lt;/p&gt;
&lt;p&gt;For Windows:&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; &amp;gt; python.exe&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For Linux:&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; &amp;gt; ./python&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For macOS:&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; &amp;gt; ./python.exe&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;Then pass this file through a module built into the standard library called &lt;code&gt;tokenize&lt;/code&gt;. You will see the list of tokens, by line and character. Use the &lt;code&gt;-e&lt;/code&gt; flag to output the exact token name:&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.exe -m tokenize -e test_tokens.py

&lt;span class=&quot;go&quot;&gt;0,0-0,0:            ENCODING       &amp;#39;utf-8&amp;#39;        &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1,0-1,14:           COMMENT        &amp;#39;# Hello world!&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1,14-1,15:          NL             &amp;#39;\n&amp;#39;           &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2,0-2,3:            NAME           &amp;#39;def&amp;#39;          &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2,4-2,15:           NAME           &amp;#39;my_function&amp;#39;  &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2,15-2,16:          LPAR           &amp;#39;(&amp;#39;            &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2,16-2,17:          RPAR           &amp;#39;)&amp;#39;            &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2,17-2,18:          COLON          &amp;#39;:&amp;#39;            &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2,18-2,19:          NEWLINE        &amp;#39;\n&amp;#39;           &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3,0-3,3:            INDENT         &amp;#39;   &amp;#39;          &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3,3-3,7:            NAME           &amp;#39;proceed&amp;#39;         &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3,7-3,8:            NEWLINE        &amp;#39;\n&amp;#39;           &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4,0-4,0:            DEDENT         &amp;#39;&amp;#39;             &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4,0-4,0:            ENDMARKER      &amp;#39;&amp;#39;              &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the output, the first column is the range of the line/column coordinates, the second column is the name of the token, and the final column is the value of the token.&lt;/p&gt;
&lt;p&gt;In the output, the &lt;code&gt;tokenize&lt;/code&gt; module has implied some tokens that were not in the file. The &lt;code&gt;ENCODING&lt;/code&gt; token for &lt;code&gt;utf-8&lt;/code&gt;, and a blank line at the end, giving &lt;code&gt;DEDENT&lt;/code&gt; to close the function declaration and an &lt;code&gt;ENDMARKER&lt;/code&gt; to end the file.&lt;/p&gt;
&lt;p&gt;It is best practice to have a blank line at the end of your Python source files. If you omit it, CPython adds it for you, with a tiny performance penalty.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;tokenize&lt;/code&gt; module is written in pure Python and is located in &lt;a href=&quot;https://github.com/python/cpython/blob/master/Lib/tokenize.py&quot;&gt;&lt;code&gt;Lib/tokenize.py&lt;/code&gt;&lt;/a&gt; within the CPython source code.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; There are two tokenizers in the CPython source code: one written in Python, demonstrated here, and another written in C.
The tokenizer written in Python is meant as a utility, and the one written in C is used by the Python compiler. They have identical output and behavior. The version written in C is designed for performance and the module in Python is designed for debugging.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To see a verbose readout of the C tokenizer, you can run Python with the &lt;code&gt;-d&lt;/code&gt; flag. Using the &lt;code&gt;test_tokens.py&lt;/code&gt; script you created earlier, run it with 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;gp&quot;&gt;$&lt;/span&gt; ./python.exe -d test_tokens.py

&lt;span class=&quot;go&quot;&gt;Token NAME/&amp;#39;def&amp;#39; ... It&amp;#39;s a keyword&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;file_input&amp;#39;, state 0: Push &amp;#39;stmt&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;stmt&amp;#39;, state 0: Push &amp;#39;compound_stmt&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;compound_stmt&amp;#39;, state 0: Push &amp;#39;funcdef&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;funcdef&amp;#39;, state 0: Shift.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Token NAME/&amp;#39;my_function&amp;#39; ... It&amp;#39;s a token we know&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;funcdef&amp;#39;, state 1: Shift.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Token LPAR/&amp;#39;(&amp;#39; ... It&amp;#39;s a token we know&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;funcdef&amp;#39;, state 2: Push &amp;#39;parameters&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;parameters&amp;#39;, state 0: Shift.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Token RPAR/&amp;#39;)&amp;#39; ... It&amp;#39;s a token we know&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;parameters&amp;#39;, state 1: Shift.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  DFA &amp;#39;parameters&amp;#39;, state 2: Direct pop.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Token COLON/&amp;#39;:&amp;#39; ... It&amp;#39;s a token we know&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;funcdef&amp;#39;, state 3: Shift.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Token NEWLINE/&amp;#39;&amp;#39; ... It&amp;#39;s a token we know&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;funcdef&amp;#39;, state 5: [switch func_body_suite to suite] Push &amp;#39;suite&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;suite&amp;#39;, state 0: Shift.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Token INDENT/&amp;#39;&amp;#39; ... It&amp;#39;s a token we know&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;suite&amp;#39;, state 1: Shift.&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;go&quot;&gt;Token NAME/&amp;#39;proceed&amp;#39; ... It&amp;#39;s a keyword&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt; DFA &amp;#39;suite&amp;#39;, state 3: Push &amp;#39;stmt&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  ACCEPT.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the output, you can see that it highlighted &lt;code&gt;proceed&lt;/code&gt; as a keyword. In the next chapter, we&amp;rsquo;ll see how executing the Python binary gets to the tokenizer and what happens from there to execute your code.&lt;/p&gt;
&lt;p&gt;Now that you have an overview of the Python grammar and the relationship between tokens and statements, there is a way to convert the &lt;code&gt;pgen&lt;/code&gt; output into an interactive graph.&lt;/p&gt;
&lt;p&gt;Here is a screenshot of the Python 3.8a2 grammar:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-12_at_2.31.16_pm.f36c3e99b8b4.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/Screen_Shot_2019-03-12_at_2.31.16_pm.f36c3e99b8b4.png&quot; width=&quot;3258&quot; height=&quot;2248&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-12_at_2.31.16_pm.f36c3e99b8b4.png&amp;amp;w=814&amp;amp;sig=21666b4228a46a6bcc7aeca6d5263e62a3aeb6d5 814w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-12_at_2.31.16_pm.f36c3e99b8b4.png&amp;amp;w=1629&amp;amp;sig=01404157eddc09548f8cf7d4e995da9806c36fac 1629w, https://files.realpython.com/media/Screen_Shot_2019-03-12_at_2.31.16_pm.f36c3e99b8b4.png 3258w&quot; sizes=&quot;75vw&quot; alt=&quot;Python 3.8 DFA node graph&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Python package used to generate this graph, &lt;code&gt;instaviz&lt;/code&gt;, will be covered in a later chapter.&lt;/p&gt;
&lt;h3 id=&quot;memory-management-in-cpython&quot;&gt;Memory Management in CPython&lt;/h3&gt;
&lt;p&gt;Throughout this article, you will see references to a &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pyarena.c#L128&quot;&gt;&lt;code&gt;PyArena&lt;/code&gt;&lt;/a&gt; object. The arena is one of CPython&amp;rsquo;s memory management structures. The code is within &lt;code&gt;Python/pyarena.c&lt;/code&gt; and contains a wrapper around C&amp;rsquo;s memory allocation and deallocation functions.&lt;/p&gt;
&lt;p&gt;In a traditionally written C program, the developer &lt;em&gt;should&lt;/em&gt; allocate memory for data structures before writing into that data. This allocation marks the memory as belonging to the process with the operating system.&lt;/p&gt;
&lt;p&gt;It is also up to the developer to deallocate, or &amp;ldquo;free,&amp;rdquo; the allocated memory when its no longer being used and return it to the operating system&amp;rsquo;s block table of free memory. 
If a process allocates memory for a variable, say within a function or loop, when that function has completed, the memory is not automatically given back to the operating system in C. So if it hasn&amp;rsquo;t been explicitly deallocated in the C code, it causes a memory leak. The process will continue to take more memory each time that function runs until eventually, the system runs out of memory, and crashes!&lt;/p&gt;
&lt;p&gt;Python takes that responsibility away from the programmer and uses two algorithms: &lt;a href=&quot;https://realpython.com/python-memory-management/&quot;&gt;a reference counter and a garbage collector&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Whenever an interpreter is instantiated, a &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pyarena.c#L128&quot;&gt;&lt;code&gt;PyArena&lt;/code&gt;&lt;/a&gt; is created and attached one of the fields in the interpreter. During the lifecycle of a CPython interpreter, many arenas could be allocated. They are connected with a linked list. The arena stores a list of pointers to Python Objects as a &lt;code&gt;PyListObject&lt;/code&gt;. Whenever a new Python object is created, a pointer to it is added using &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pyarena.c#L203&quot;&gt;&lt;code&gt;PyArena_AddPyObject()&lt;/code&gt;&lt;/a&gt;. This function call stores a pointer in the arena&amp;rsquo;s list, &lt;code&gt;a_objects&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;Even though Python doesn&amp;rsquo;t have pointers, there are some &lt;a href=&quot;https://realpython.com/pointers-in-python/&quot;&gt;interesting techniques&lt;/a&gt; to simulate the behavior of pointers.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;PyArena&lt;/code&gt; serves a second function, which is to allocate and reference a list of raw memory blocks. For example, a &lt;code&gt;PyList&lt;/code&gt; would need extra memory if you added thousands of additional values. The &lt;code&gt;PyList&lt;/code&gt; object&amp;rsquo;s C code does not allocate memory directly. The object gets raw blocks of memory from the &lt;code&gt;PyArena&lt;/code&gt; by calling &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pyarena.c#L180&quot;&gt;&lt;code&gt;PyArena_Malloc()&lt;/code&gt;&lt;/a&gt; from the &lt;code&gt;PyObject&lt;/code&gt; with the required memory size. This task is completed by another abstraction in &lt;code&gt;Objects/obmalloc.c&lt;/code&gt;. In the object allocation module, memory can be allocated, freed, and reallocated for a Python Object.&lt;/p&gt;
&lt;p&gt;A linked list of allocated blocks is stored inside the arena, so that when an interpreter is stopped, all managed memory blocks can be deallocated in one go using &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pyarena.c#L157&quot;&gt;&lt;code&gt;PyArena_Free()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Take the &lt;code&gt;PyListObject&lt;/code&gt; example. If you were to &lt;code&gt;.append()&lt;/code&gt; an object to the end of a Python list, you don&amp;rsquo;t need to reallocate the memory used in the existing list beforehand. The &lt;code&gt;.append()&lt;/code&gt; method calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/listobject.c#L36&quot;&gt;&lt;code&gt;list_resize()&lt;/code&gt;&lt;/a&gt; which handles memory allocation for lists. Each list object keeps a list of the amount of memory allocated. If the item you&amp;rsquo;re appending will fit inside the existing free memory, it is simply added. If the list needs more memory space, it is expanded. Lists are expanded in length as 0, 4, 8, 16, 25, 35, 46, 58, 72, 88.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/obmalloc.c#L618&quot;&gt;&lt;code&gt;PyMem_Realloc()&lt;/code&gt;&lt;/a&gt; is called to expand the memory allocated in a list. &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/obmalloc.c#L618&quot;&gt;&lt;code&gt;PyMem_Realloc()&lt;/code&gt;&lt;/a&gt; is an API wrapper for &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/obmalloc.c#L1913&quot;&gt;&lt;code&gt;pymalloc_realloc()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Python also has a special wrapper for the C call &lt;code&gt;malloc()&lt;/code&gt;, which sets the max size of the memory allocation to help prevent buffer overflow errors (See &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Modules/overlapped.c#L28&quot;&gt;&lt;code&gt;PyMem_RawMalloc()&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In summary: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allocation of raw memory blocks is done via &lt;code&gt;PyMem_RawAlloc()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The pointers to Python objects are stored within the &lt;code&gt;PyArena&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PyArena&lt;/code&gt; also stores a linked-list of allocated memory blocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More information on the API is detailed on the &lt;a href=&quot;https://docs.python.org/3/c-api/memory.html&quot;&gt;CPython documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;reference-counting&quot;&gt;Reference Counting&lt;/h4&gt;
&lt;p&gt;To create a variable in Python, you have to assign a value to a &lt;em&gt;uniquely&lt;/em&gt; named variable:&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;my_variable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;180392&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Whenever a value is assigned to a variable in Python, the name of the variable is checked within the locals and globals scope to see if it already exists.&lt;/p&gt;
&lt;p&gt;Because &lt;code&gt;my_variable&lt;/code&gt; is not already within the &lt;code&gt;locals()&lt;/code&gt; or &lt;code&gt;globals()&lt;/code&gt; dictionary, this new object is created, and the value is assigned as being the numeric constant &lt;code&gt;180392&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is now one reference to &lt;code&gt;my_variable&lt;/code&gt;, so the reference counter for &lt;code&gt;my_variable&lt;/code&gt; is incremented by 1. &lt;/p&gt;
&lt;p&gt;You will see function calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L239&quot;&gt;&lt;code&gt;Py_INCREF()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L245&quot;&gt;&lt;code&gt;Py_DECREF()&lt;/code&gt;&lt;/a&gt; throughout the C source code for CPython. These functions increment and decrement the count of references to that object.&lt;/p&gt;
&lt;p&gt;References to an object are decremented when a variable falls outside of the scope in which it was declared. Scope in Python can refer to a function or method, a comprehension, or a lambda function. These are some of the more literal scopes, but there are many other implicit scopes, like passing variables to a function call.&lt;/p&gt;
&lt;p&gt;The handling of incrementing and decrementing references based on the language is built into the CPython compiler and the core execution loop, &lt;code&gt;ceval.c&lt;/code&gt;, which we will cover in detail later in this article.&lt;/p&gt;
&lt;p&gt;Whenever &lt;code&gt;Py_DECREF()&lt;/code&gt; is called, and the counter becomes 0, the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/obmalloc.c#L707&quot;&gt;&lt;code&gt;PyObject_Free()&lt;/code&gt;&lt;/a&gt; function is called. For that object &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pyarena.c#L157&quot;&gt;&lt;code&gt;PyArena_Free()&lt;/code&gt;&lt;/a&gt; is called for all of the memory that was allocated. &lt;/p&gt;
&lt;h4 id=&quot;garbage-collection&quot;&gt;Garbage Collection&lt;/h4&gt;
&lt;p&gt;How often does your garbage get collected? Weekly, or fortnightly? &lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re finished with something, you discard it and throw it in the trash. But that trash won&amp;rsquo;t get collected straight away. You need to wait for the garbage trucks to come and pick it up.&lt;/p&gt;
&lt;p&gt;CPython has the same principle, using a garbage collection algorithm. CPython&amp;rsquo;s garbage collector is enabled by default, happens in the background and works to deallocate memory that&amp;rsquo;s been used for objects which are no longer in use.&lt;/p&gt;
&lt;p&gt;Because the garbage collection algorithm is a lot more complex than the reference counter, it doesn&amp;rsquo;t happen all the time, otherwise, it would consume a huge amount of CPU resources. It happens periodically, after a set number of operations.&lt;/p&gt;
&lt;p&gt;CPython&amp;rsquo;s standard library comes with a Python module to interface with the arena and the garbage collector, the &lt;code&gt;gc&lt;/code&gt; module. Here&amp;rsquo;s how to use the &lt;code&gt;gc&lt;/code&gt; module in debug mode:&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;gc&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DEBUG_STATS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will print the statistics whenever the garbage collector is run.&lt;/p&gt;
&lt;p&gt;You can get the threshold after which the garbage collector is run by calling &lt;code&gt;get_threshold()&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;gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(700, 10, 10)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also get the current threshold counts:&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;gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(688, 1, 1)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lastly, you can run the collection algorithm manually:&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;gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;24&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will call &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Modules/gcmodule.c#L987&quot;&gt;&lt;code&gt;collect()&lt;/code&gt;&lt;/a&gt; inside the &lt;code&gt;Modules/gcmodule.c&lt;/code&gt; file which contains the implementation of the garbage collector algorithm.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In Part 1, you covered the structure of the source code repository, how to compile from source, and the Python language specification. These core concepts will be critical in Part 2 as you dive deeper into the Python interpreter process.&lt;/p&gt;
&lt;h2 h1=&quot;h1&quot; id=&quot;part-2-the-python-interpreter-process&quot;&gt;Part 2: The Python Interpreter Process&lt;/h2&gt;
&lt;p&gt;Now that you&amp;rsquo;ve seen the Python grammar and memory management, you can follow the process from typing &lt;code&gt;python&lt;/code&gt; to the part where your code is executed.&lt;/p&gt;
&lt;p&gt;There are five ways the &lt;code&gt;python&lt;/code&gt; binary can be called:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;To run a single command with &lt;code&gt;-c&lt;/code&gt; and a Python command&lt;/li&gt;
&lt;li&gt;To start a module with &lt;code&gt;-m&lt;/code&gt; and the name of a module&lt;/li&gt;
&lt;li&gt;To run a file with the filename&lt;/li&gt;
&lt;li&gt;To run the &lt;code&gt;stdin&lt;/code&gt; input using a shell pipe&lt;/li&gt;
&lt;li&gt;To start the REPL and execute commands one at a time&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;Python has so many ways to execute scripts, it can be a little overwhelming. Darren Jones has put together a &lt;a href=&quot;https://realpython.com/courses/running-python-scripts/&quot;&gt;great course on running Python scripts&lt;/a&gt; if you want to learn more.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The three source files you need to inspect to see this process are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Programs/python.c&lt;/code&gt;&lt;/strong&gt; is a simple entry point.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Modules/main.c&lt;/code&gt;&lt;/strong&gt; contains the code to bring together the whole process, loading configuration, executing code and clearing up memory.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Python/initconfig.c&lt;/code&gt;&lt;/strong&gt; loads the configuration from the system environment and merges it with any command-line flags.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This diagram shows how each of those functions is called:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/swim-lanes-chart-1.9fb3000aad85.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/swim-lanes-chart-1.9fb3000aad85.png&quot; width=&quot;1046&quot; height=&quot;851&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/swim-lanes-chart-1.9fb3000aad85.png&amp;amp;w=261&amp;amp;sig=8aa36cedaf32be0236896cce2c32b6c4c4ec7e05 261w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/swim-lanes-chart-1.9fb3000aad85.png&amp;amp;w=523&amp;amp;sig=a447b53d2afa96dfd204b9265c8b439bd71272d7 523w, https://files.realpython.com/media/swim-lanes-chart-1.9fb3000aad85.png 1046w&quot; sizes=&quot;75vw&quot; alt=&quot;Python run swim lane diagram&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The execution mode is determined from the configuration.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;The CPython source code style:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Similar to the &lt;a href=&quot;https://realpython.com/courses/writing-beautiful-python-code-pep-8/&quot;&gt;PEP8 style guide for Python code&lt;/a&gt;, there is an &lt;a href=&quot;https://www.python.org/dev/peps/pep-0007/&quot;&gt;official style guide&lt;/a&gt; for the CPython C code, designed originally in 2001 and updated for modern versions. &lt;/p&gt;
&lt;p&gt;There are some naming standards which help when navigating the source code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use a &lt;code&gt;Py&lt;/code&gt; prefix for public functions, never for static functions. The &lt;code&gt;Py_&lt;/code&gt; prefix is reserved for global service routines like &lt;code&gt;Py_FatalError&lt;/code&gt;. Specific groups of routines (like specific object type APIs) use a longer prefix, such as &lt;code&gt;PyString_&lt;/code&gt; for string functions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Public functions and variables use MixedCase with underscores, like this: &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L924&quot;&gt;&lt;code&gt;PyObject_GetAttr&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/modsupport.h#L20&quot;&gt;&lt;code&gt;Py_BuildValue&lt;/code&gt;&lt;/a&gt;, &lt;code&gt;PyExc_TypeError&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Occasionally an &amp;ldquo;internal&amp;rdquo; function has to be visible to the loader. We use the &lt;code&gt;_Py&lt;/code&gt; prefix for this, for example, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L464&quot;&gt;&lt;code&gt;_PyObject_Dump&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Macros should have a MixedCase prefix and then use upper case, for example &lt;code&gt;PyString_AS_STRING&lt;/code&gt;, &lt;code&gt;Py_PRINT_RAW&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&quot;establishing-runtime-configuration&quot;&gt;Establishing Runtime Configuration&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/swim-lanes-chart-1.9fb3000aad85.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/swim-lanes-chart-1.9fb3000aad85.png&quot; width=&quot;1046&quot; height=&quot;851&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/swim-lanes-chart-1.9fb3000aad85.png&amp;amp;w=261&amp;amp;sig=8aa36cedaf32be0236896cce2c32b6c4c4ec7e05 261w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/swim-lanes-chart-1.9fb3000aad85.png&amp;amp;w=523&amp;amp;sig=a447b53d2afa96dfd204b9265c8b439bd71272d7 523w, https://files.realpython.com/media/swim-lanes-chart-1.9fb3000aad85.png 1046w&quot; sizes=&quot;75vw&quot; alt=&quot;Python run swim lane diagram&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the swimlanes, you can see that before any Python code is executed, the runtime first establishes the configuration.
The configuration of the runtime is a data structure defined in &lt;code&gt;Include/cpython/initconfig.h&lt;/code&gt; named &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/cpython/initconfig.h#L407&quot;&gt;&lt;code&gt;PyConfig&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The configuration data structure includes things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Runtime flags for various modes like debug and optimized mode&lt;/li&gt;
&lt;li&gt;The execution mode, such as whether a filename was passed, &lt;code&gt;stdin&lt;/code&gt; was provided or a module name&lt;/li&gt;
&lt;li&gt;Extended option, specified by &lt;code&gt;-X &amp;lt;option&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Environment variables for runtime settings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The configuration data is primarily used by the CPython runtime to enable and disable various features.&lt;/p&gt;
&lt;p&gt;Python also comes with several &lt;a href=&quot;https://docs.python.org/3/using/cmdline.html&quot;&gt;Command Line Interface Options&lt;/a&gt;. In Python you can enable verbose mode with the &lt;code&gt;-v&lt;/code&gt; flag. In verbose mode, Python will print messages to the screen when modules are loaded:&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.exe -v -c &lt;span class=&quot;s2&quot;&gt;&amp;quot;print(&amp;#39;hello world&amp;#39;)&amp;quot;&lt;/span&gt;


&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; installing zipimport hook
&lt;span class=&quot;go&quot;&gt;import zipimport # builtin&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; installed zipimport hook
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You will see a hundred lines or more with all the imports of your user site-packages and anything else in the system environment.&lt;/p&gt;
&lt;p&gt;You can see the definition of this flag within &lt;code&gt;Include/cpython/initconfig.h&lt;/code&gt; inside the &lt;code&gt;struct&lt;/code&gt; for &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/cpython/initconfig.h#L407&quot;&gt;&lt;code&gt;PyConfig&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* --- PyConfig ---------------------------------------------- */&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_config_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/* Internal configuration version,&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                             used for ABI compatibility */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_config_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;cm&quot;&gt;/* _PyConfigInitEnum value */&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* If greater than 0, enable the verbose mode: print a message each time a&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       module is initialized, showing the place (filename or built-in module)&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       from which it is loaded.&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;       If greater or equal to 2, print a message for each file that is checked&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       for when searching for a module. Also provides information on module&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       cleanup at exit.&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;       Incremented by the -v option. Set by the PYTHONVERBOSE environment&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       variable. If set to -1 (default), inherit Py_VerboseFlag value. */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;Python/initconfig.c&lt;/code&gt;, the logic for reading settings from environment variables and runtime command-line flags is established.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;config_read_env_vars&lt;/code&gt; function, the environment variables are read and used to assign the values for the configuration settings:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyStatus&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;config_read_env_vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&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;PyStatus&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;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use_env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use_environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* Get environment variables */&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;_Py_get_env_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use_env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser_debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;PYTHONDEBUG&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;_Py_get_env_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use_env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;PYTHONVERBOSE&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_Py_get_env_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use_env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;optimization_level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;PYTHONOPTIMIZE&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_Py_get_env_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use_env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inspect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;PYTHONINSPECT&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For the verbose setting, you can see that the value of &lt;code&gt;PYTHONVERBOSE&lt;/code&gt; is used to set the value of &lt;code&gt;&amp;amp;config-&amp;gt;verbose&lt;/code&gt;, if &lt;code&gt;PYTHONVERBOSE&lt;/code&gt; is found. If the environment variable does not exist, then the default value of &lt;code&gt;-1&lt;/code&gt; will remain.&lt;/p&gt;
&lt;p&gt;Then in &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/initconfig.c#L1828&quot;&gt;&lt;code&gt;config_parse_cmdline&lt;/code&gt;&lt;/a&gt; within &lt;code&gt;initconfig.c&lt;/code&gt; again, the command-line flag is used to set the value, if provided:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyStatus&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;config_parse_cmdline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyWideStringList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warnoptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                     &lt;span class=&quot;n&quot;&gt;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt_index&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;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;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;case&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&amp;#39;v&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;            &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;break&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;cm&quot;&gt;/* This space reserved for other options */&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;cm&quot;&gt;/* unknown argument: parsing failed */&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;config_usage&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;program&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;_PyStatus_EXIT&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;p&quot;&gt;}&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;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;This value is later copied to a global variable &lt;code&gt;Py_VerboseFlag&lt;/code&gt; by the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/initconfig.c#L134&quot;&gt;&lt;code&gt;_Py_GetGlobalVariablesAsDict&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;
&lt;p&gt;Within a Python session, you can access the runtime flags, like verbose mode, quiet mode, using the &lt;code&gt;sys.flags&lt;/code&gt; named tuple.
The &lt;code&gt;-X&lt;/code&gt; flags are all available inside the &lt;code&gt;sys._xoptions&lt;/code&gt; dictionary:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;$ ./python.exe -X dev -q       &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;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;sys.flags(debug=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; no_user_site=0, no_site=0, ignore_environment=0, verbose=0, bytes_warning=0, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; quiet=1, hash_randomization=1, isolated=0, dev_mode=True, utf8_mode=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;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_xoptions&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;dev&amp;#39;: True}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As well as the runtime configuration in &lt;code&gt;initconfig.h&lt;/code&gt;, there is also the build configuration, which is located inside &lt;code&gt;pyconfig.h&lt;/code&gt; in the root folder. This file is created dynamically in the &lt;code&gt;configure&lt;/code&gt; step in the build process, or by Visual Studio for Windows systems.&lt;/p&gt;
&lt;p&gt;You can see the build configuration by running:&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.exe -m sysconfig
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;reading-filesinput&quot;&gt;Reading Files/Input&lt;/h3&gt;
&lt;p&gt;Once CPython has the runtime configuration and the command-line arguments, it can establish what it needs to execute.&lt;/p&gt;
&lt;p&gt;This task is handled by the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Modules/main.c#L665&quot;&gt;&lt;code&gt;pymain_main&lt;/code&gt;&lt;/a&gt; function inside &lt;code&gt;Modules/main.c&lt;/code&gt;. Depending on the newly created &lt;code&gt;config&lt;/code&gt; instance, CPython will now execute code provided via several options.&lt;/p&gt;
&lt;h4 id=&quot;input-via-c&quot;&gt;Input via &lt;code&gt;-c&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;The simplest is providing CPython a command with the &lt;code&gt;-c&lt;/code&gt; option and a Python program inside quotes.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./python.exe -c &lt;span class=&quot;s2&quot;&gt;&amp;quot;print(&amp;#39;hi&amp;#39;)&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;hi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is the full flowchart of how this happens:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pymain_run_command.f5da561ba7d5.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/pymain_run_command.f5da561ba7d5.png&quot; width=&quot;1041&quot; height=&quot;751&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pymain_run_command.f5da561ba7d5.png&amp;amp;w=260&amp;amp;sig=f7f802b23e900bf42b29804ee80ed0dd0eaec6a4 260w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pymain_run_command.f5da561ba7d5.png&amp;amp;w=520&amp;amp;sig=3079060f305945fd3556ce7cd453fac965a6ec27 520w, https://files.realpython.com/media/pymain_run_command.f5da561ba7d5.png 1041w&quot; sizes=&quot;75vw&quot; alt=&quot;Flow chart of pymain_run_command&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;First, the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Modules/main.c#L240&quot;&gt;&lt;code&gt;pymain_run_command()&lt;/code&gt;&lt;/a&gt; function is executed inside &lt;code&gt;Modules/main.c&lt;/code&gt; taking the command passed in &lt;code&gt;-c&lt;/code&gt; as an argument in the C type &lt;code&gt;wchar_t*&lt;/code&gt;. The &lt;code&gt;wchar_t*&lt;/code&gt; type is often used as a low-level storage type for Unicode data across CPython as the size of the type can store UTF8 characters.&lt;/p&gt;
&lt;p&gt;When converting the &lt;code&gt;wchar_t*&lt;/code&gt; to a Python string, the &lt;code&gt;Objects/unicodeobject.c&lt;/code&gt; file has a helper function &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/unicodeobject.c#L2088&quot;&gt;&lt;code&gt;PyUnicode_FromWideChar()&lt;/code&gt;&lt;/a&gt; that returns a &lt;code&gt;PyObject&lt;/code&gt;, of type &lt;code&gt;str&lt;/code&gt;. The encoding to UTF8 is then done by &lt;code&gt;PyUnicode_AsUTF8String()&lt;/code&gt; on the Python &lt;code&gt;str&lt;/code&gt; object to convert it to a Python &lt;code&gt;bytes&lt;/code&gt; object. &lt;/p&gt;
&lt;p&gt;Once this is complete, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Modules/main.c#L240&quot;&gt;&lt;code&gt;pymain_run_command()&lt;/code&gt;&lt;/a&gt; will then pass the Python bytes object to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L453&quot;&gt;&lt;code&gt;PyRun_SimpleStringFlags()&lt;/code&gt;&lt;/a&gt; for execution, but first converting the &lt;code&gt;bytes&lt;/code&gt; to a &lt;code&gt;str&lt;/code&gt; type again:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;pymain_run_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cf&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicode&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;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;unicode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyUnicode_FromWideChar&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;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;PySys_Audit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;cpython.run_command&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;O&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pymain_exit_err_print&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;bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyUnicode_AsUTF8String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicode&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;bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyRun_SimpleStringFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyBytes_AsString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bytes&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&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;nl&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PySys_WriteStderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Unable to decode the command from the command line:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pymain_exit_err_print&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 conversion of &lt;code&gt;wchar_t*&lt;/code&gt; to Unicode, bytes, and then a string is roughly equivalent to the following:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bytes_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;utf8&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# call PyRun_SimpleStringFlags with bytes_&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L453&quot;&gt;&lt;code&gt;PyRun_SimpleStringFlags()&lt;/code&gt;&lt;/a&gt; function is part of &lt;code&gt;Python/pythonrun.c&lt;/code&gt;. It&amp;rsquo;s purpose is to turn this simple command into a Python module and then send it on to be executed.
Since a Python module needs to have &lt;code&gt;__main__&lt;/code&gt; to be executed as a standalone module, it creates that automatically:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyRun_SimpleStringFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&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;d&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;v&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;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyImport_AddModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;__main__&amp;quot;&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;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;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyModule_GetDict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyRun_StringFlags&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_file_input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;PyErr_Print&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;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L453&quot;&gt;&lt;code&gt;PyRun_SimpleStringFlags()&lt;/code&gt;&lt;/a&gt; has created a module and a dictionary, it calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1008&quot;&gt;&lt;code&gt;PyRun_StringFlags()&lt;/code&gt;&lt;/a&gt;, which creates a fake filename and then calls the Python parser to create an AST from the string and return a module, &lt;code&gt;mod&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyRun_StringFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyParser_ASTFromStringObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&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;mod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyArena_Free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arena&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;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll dive into the AST and Parser code in the next section.&lt;/p&gt;
&lt;h4 id=&quot;input-via-m&quot;&gt;Input via &lt;code&gt;-m&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Another way to execute Python commands is by using the &lt;code&gt;-m&lt;/code&gt; option with the name of a module.
A typical example is &lt;code&gt;python -m unittest&lt;/code&gt; to run the unittest module in the standard library.&lt;/p&gt;
&lt;p&gt;Being able to execute modules as scripts were initially proposed in &lt;a href=&quot;https://www.python.org/dev/peps/pep-0338&quot;&gt;PEP 338&lt;/a&gt; and then the standard for explicit relative imports defined in &lt;a href=&quot;https://www.python.org/dev/peps/pep-0366&quot;&gt;PEP366&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;The use of the &lt;code&gt;-m&lt;/code&gt; flag implies that within the module package, you want to execute whatever is inside &lt;a href=&quot;https://realpython.com/python-main-function/&quot;&gt;&lt;code&gt;__main__&lt;/code&gt;&lt;/a&gt;. It also implies that you want to search &lt;code&gt;sys.path&lt;/code&gt; for the named module.&lt;/p&gt;
&lt;p&gt;This search mechanism is why you don&amp;rsquo;t need to remember where the &lt;code&gt;unittest&lt;/code&gt; module is stored on your filesystem.&lt;/p&gt;
&lt;p&gt;Inside &lt;code&gt;Modules/main.c&lt;/code&gt; there is a function called when the command-line is run with the &lt;code&gt;-m&lt;/code&gt; flag. The name of the module is passed as the &lt;code&gt;modname&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;CPython will then import a standard library module, &lt;code&gt;runpy&lt;/code&gt; and execute it using &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/call.c#L214&quot;&gt;&lt;code&gt;PyObject_Call()&lt;/code&gt;&lt;/a&gt;. The import is done using the C API function &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/import.c#L1409&quot;&gt;&lt;code&gt;PyImport_ImportModule()&lt;/code&gt;&lt;/a&gt;, found within the &lt;code&gt;Python/import.c&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;pymain_run_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set_argv0&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module&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;runpy&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;runmodule&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;runargs&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;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;runpy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyImport_ImportModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;runpy&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;runmodule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject_GetAttrString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;_run_module_as_main&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyUnicode_FromWideChar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wcslen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modname&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;runargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_BuildValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;(Oi)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set_argv0&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;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject_Call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runmodule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&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;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pymain_exit_err_print&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;Py_DECREF&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;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this function you&amp;rsquo;ll also see 2 other C API functions: &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/call.c#L214&quot;&gt;&lt;code&gt;PyObject_Call()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L831&quot;&gt;&lt;code&gt;PyObject_GetAttrString()&lt;/code&gt;&lt;/a&gt;. Because &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/import.c#L1409&quot;&gt;&lt;code&gt;PyImport_ImportModule()&lt;/code&gt;&lt;/a&gt; returns a &lt;code&gt;PyObject*&lt;/code&gt;, the core object type, you need to call special functions to get attributes and to call it.&lt;/p&gt;
&lt;p&gt;In Python, if you had an object and wanted to get an attribute, then you could call &lt;code&gt;getattr()&lt;/code&gt;. In the C API, this call is &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L831&quot;&gt;&lt;code&gt;PyObject_GetAttrString()&lt;/code&gt;&lt;/a&gt;, which is found in &lt;code&gt;Objects/object.c&lt;/code&gt;. If you wanted to run a callable, you would give it parentheses, or you can run the &lt;code&gt;__call__()&lt;/code&gt; property on any Python object. The &lt;code&gt;__call__()&lt;/code&gt; method is implemented inside &lt;code&gt;Objects/object.c&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;hi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hi!&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&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;hi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;__call__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# this is the same&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;runpy&lt;/code&gt; module is written in pure Python and located in &lt;code&gt;Lib/runpy.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Executing &lt;code&gt;python -m &amp;lt;module&amp;gt;&lt;/code&gt; is equivalent to running &lt;code&gt;python -m runpy &amp;lt;module&amp;gt;&lt;/code&gt;. The &lt;code&gt;runpy&lt;/code&gt; module was created to abstract the process of locating and executing modules on an operating system.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;runpy&lt;/code&gt; does a few things to run the target module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Calls &lt;code&gt;__import__()&lt;/code&gt; for the module name you provided&lt;/li&gt;
&lt;li&gt;Sets &lt;code&gt;__name__&lt;/code&gt; (the module name) to a namespace called &lt;code&gt;__main__&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Executes the module within the &lt;code&gt;__main__&lt;/code&gt; namespace&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;runpy&lt;/code&gt; module also supports executing directories and zip files.&lt;/p&gt;
&lt;h4 id=&quot;input-via-filename&quot;&gt;Input via Filename&lt;/h4&gt;
&lt;p&gt;If the first argument to &lt;code&gt;python&lt;/code&gt; was a filename, such as &lt;code&gt;python test.py&lt;/code&gt;, then CPython will open a file handle, similar to using &lt;code&gt;open()&lt;/code&gt; in Python and pass the handle to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L372&quot;&gt;&lt;code&gt;PyRun_SimpleFileExFlags()&lt;/code&gt;&lt;/a&gt; inside &lt;code&gt;Python/pythonrun.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are 3 paths this function can take:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If the file path is a &lt;code&gt;.pyc&lt;/code&gt; file, it will call &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1145&quot;&gt;&lt;code&gt;run_pyc_file()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If the file path is a script file (&lt;code&gt;.py&lt;/code&gt;) it will run &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1032&quot;&gt;&lt;code&gt;PyRun_FileExFlags()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If the filepath is &lt;code&gt;stdin&lt;/code&gt; because the user ran &lt;code&gt;command | python&lt;/code&gt; then treat &lt;code&gt;stdin&lt;/code&gt; as a file handle and run &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1032&quot;&gt;&lt;code&gt;PyRun_FileExFlags()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyRun_SimpleFileExFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;closeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyImport_AddModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;__main__&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;hll&quot;&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;maybe_pyc_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;closeit&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&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;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_pyc_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyc_fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&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;cm&quot;&gt;/* When running from stdin, leave __main__.__loader__ alone */&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;strcmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;set_main_loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;SourceFileLoader&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;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;n&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;python: failed to set __main__.__loader__&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ret&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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;done&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;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyRun_FileExFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_file_input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;                              &lt;span class=&quot;n&quot;&gt;closeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&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;h4 id=&quot;input-via-file-with-pyrun_fileexflags&quot;&gt;Input via File With &lt;code&gt;PyRun_FileExFlags()&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;For &lt;code&gt;stdin&lt;/code&gt; and basic script files, CPython will pass the file handle to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1032&quot;&gt;&lt;code&gt;PyRun_FileExFlags()&lt;/code&gt;&lt;/a&gt; located in the &lt;code&gt;pythonrun.c&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;The purpose of &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1032&quot;&gt;&lt;code&gt;PyRun_FileExFlags()&lt;/code&gt;&lt;/a&gt; is similar to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L453&quot;&gt;&lt;code&gt;PyRun_SimpleStringFlags()&lt;/code&gt;&lt;/a&gt; used for the &lt;code&gt;-c&lt;/code&gt; input. CPython will load the file handle into &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1369&quot;&gt;&lt;code&gt;PyParser_ASTFromFileObject()&lt;/code&gt;&lt;/a&gt;. We&amp;rsquo;ll cover the Parser and AST modules in the next section.
Because this is a full script, it doesn&amp;rsquo;t need the &lt;code&gt;PyImport_AddModule(&quot;__main__&quot;);&lt;/code&gt; step used by &lt;code&gt;-c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyRun_FileExFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;closeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyParser_ASTFromFileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&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;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;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&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;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&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;Identical to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L453&quot;&gt;&lt;code&gt;PyRun_SimpleStringFlags()&lt;/code&gt;&lt;/a&gt;, once &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1032&quot;&gt;&lt;code&gt;PyRun_FileExFlags()&lt;/code&gt;&lt;/a&gt; has created a Python module from the file, it sent it to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1125&quot;&gt;&lt;code&gt;run_mod()&lt;/code&gt;&lt;/a&gt; to be executed.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1125&quot;&gt;&lt;code&gt;run_mod()&lt;/code&gt;&lt;/a&gt; is found within &lt;code&gt;Python/pythonrun.c&lt;/code&gt;, and sends the module to the AST to be compiled into a code object. Code objects are a format used to store the bytecode operations and the format kept in &lt;code&gt;.pyc&lt;/code&gt; files:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;run_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyArena&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arena&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;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyAST_CompileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&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;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;PySys_Audit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;exec&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;O&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;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;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_eval_code_obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&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;v&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;We will cover the CPython compiler and bytecodes in the next section. The call to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1094&quot;&gt;&lt;code&gt;run_eval_code_obj()&lt;/code&gt;&lt;/a&gt; is a simple wrapper function that calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L716&quot;&gt;&lt;code&gt;PyEval_EvalCode()&lt;/code&gt;&lt;/a&gt; in the &lt;code&gt;Python/eval.c&lt;/code&gt; file. The &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L716&quot;&gt;&lt;code&gt;PyEval_EvalCode()&lt;/code&gt;&lt;/a&gt; function is the main evaluation loop for CPython, it iterates over each bytecode statement and executes it on your local machine.&lt;/p&gt;
&lt;h4 id=&quot;input-via-compiled-bytecode-with-run_pyc_file&quot;&gt;Input via Compiled Bytecode With &lt;code&gt;run_pyc_file()&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;In the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L372&quot;&gt;&lt;code&gt;PyRun_SimpleFileExFlags()&lt;/code&gt;&lt;/a&gt; there was a clause for the user providing a file path to a &lt;code&gt;.pyc&lt;/code&gt; file. If the file path ended in &lt;code&gt;.pyc&lt;/code&gt; then instead of loading the file as a plain text file and parsing it, it will assume that the &lt;code&gt;.pyc&lt;/code&gt; file contains a code object written to disk. &lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1145&quot;&gt;&lt;code&gt;run_pyc_file()&lt;/code&gt;&lt;/a&gt; function inside &lt;code&gt;Python/pythonrun.c&lt;/code&gt; then marshals the code object from the &lt;code&gt;.pyc&lt;/code&gt; file by using the file handle. &lt;strong&gt;Marshaling&lt;/strong&gt; is a technical term for copying the contents of a file into memory and converting them to a specific data structure. The code object data structure on the disk is the CPython compiler&amp;rsquo;s way to caching compiled code so that it doesn&amp;rsquo;t need to parse it every time the script is called:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;run_pyc_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
             &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&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;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyMarshal_ReadLastObjectFromFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&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;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyCode_Check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_XDECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_RuntimeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;s&quot;&gt;&amp;quot;Bad code object in .pyc file&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&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;co&lt;/span&gt; &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;PyCodeObject&lt;/span&gt; &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;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_eval_code_obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locals&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cf_flags&lt;/span&gt; &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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCF_MASK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&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;v&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;Once the code object has been marshaled to memory, it is sent to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1094&quot;&gt;&lt;code&gt;run_eval_code_obj()&lt;/code&gt;&lt;/a&gt;, which calls &lt;code&gt;Python/ceval.c&lt;/code&gt; to execute the code.&lt;/p&gt;
&lt;h3 id=&quot;lexing-and-parsing&quot;&gt;Lexing and Parsing&lt;/h3&gt;
&lt;p&gt;In the exploration of reading and executing Python files, we dived as deep as the parser and AST modules, with function calls to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1369&quot;&gt;&lt;code&gt;PyParser_ASTFromFileObject()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sticking within &lt;code&gt;Python/pythonrun.c&lt;/code&gt;, the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1369&quot;&gt;&lt;code&gt;PyParser_ASTFromFileObject()&lt;/code&gt;&lt;/a&gt; function will take a file handle, compiler flags and a &lt;code&gt;PyArena&lt;/code&gt; instance and convert the file object into a node object using &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/parsetok.c#L163&quot;&gt;&lt;code&gt;PyParser_ParseFileObject()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With the node object, it will then convert that into a module using the AST function &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L772&quot;&gt;&lt;code&gt;PyAST_FromNodeObject()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod_ty&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyParser_ASTFromFileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ps1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ps2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;PyArena&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arena&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;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyParser_ParseFileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enc&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_PyParser_Grammar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;                                       &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ps1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ps2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iflags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&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;n&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;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cf_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iflags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCF_MASK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyAST_FromNodeObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;PyNode_Free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&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;For &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/parsetok.c#L163&quot;&gt;&lt;code&gt;PyParser_ParseFileObject()&lt;/code&gt;&lt;/a&gt; we switch to &lt;code&gt;Parser/parsetok.c&lt;/code&gt; and the parser-tokenizer stage of the CPython interpreter. This function has two important tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Instantiate a tokenizer state &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/tokenizer.h#L23&quot;&gt;&lt;code&gt;tok_state&lt;/code&gt;&lt;/a&gt; using &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/tokenizer.h#L78&quot;&gt;&lt;code&gt;PyTokenizer_FromFile()&lt;/code&gt;&lt;/a&gt; in &lt;code&gt;Parser/tokenizer.c&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Convert the tokens into a concrete parse tree (a list of &lt;code&gt;node&lt;/code&gt;) using &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/parsetok.c#L232&quot;&gt;&lt;code&gt;parsetok()&lt;/code&gt;&lt;/a&gt; in &lt;code&gt;Parser/parsetok.c&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyParser_ParseFileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                         &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;grammar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                         &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ps1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ps2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                         &lt;span class=&quot;n&quot;&gt;perrdetail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err_ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&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;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tok_state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyTokenizer_FromFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ps1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ps2&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;NULL&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&gt;        &lt;span class=&quot;n&quot;&gt;err_ret&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;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;E_NOMEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parsetok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&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;err_ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&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;tok_state&lt;/code&gt; (defined in &lt;code&gt;Parser/tokenizer.h&lt;/code&gt;) is the data structure to store all temporary data generated by the tokenizer. It is returned to the parser-tokenizer as the data structure is required by &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/parsetok.c#L232&quot;&gt;&lt;code&gt;parsetok()&lt;/code&gt;&lt;/a&gt; to develop the concrete syntax tree.&lt;/p&gt;
&lt;p&gt;Inside &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/parsetok.c#L232&quot;&gt;&lt;code&gt;parsetok()&lt;/code&gt;&lt;/a&gt;, it will use the &lt;code&gt;tok_state&lt;/code&gt; structure and make calls to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/tokenizer.c#L1110&quot;&gt;&lt;code&gt;tok_get()&lt;/code&gt;&lt;/a&gt; in a loop until the file is exhausted and no more tokens can be found.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/tokenizer.c#L1110&quot;&gt;&lt;code&gt;tok_get()&lt;/code&gt;&lt;/a&gt;, defined in &lt;code&gt;Parser/tokenizer.c&lt;/code&gt; behaves like an iterator. It will keep returning the next token in the parse tree.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/tokenizer.c#L1110&quot;&gt;&lt;code&gt;tok_get()&lt;/code&gt;&lt;/a&gt; is one of the most complex functions in the whole CPython codebase. It has over 640 lines and includes decades of heritage with edge cases, new language features, and syntax.&lt;/p&gt;
&lt;p&gt;One of the simpler examples would be the part that converts a newline break into a NEWLINE token:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;tok_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tok_state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_end&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;cm&quot;&gt;/* Newline */&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;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&amp;#39;\n&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;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atbol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blankline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt; &lt;span class=&quot;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;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nextline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cur&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;cm&quot;&gt;/* Leave &amp;#39;\n&amp;#39; out of the string */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cont_line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async_def&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;cm&quot;&gt;/* We&amp;#39;re somewhere inside an &amp;#39;async def&amp;#39; function, and&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;               we&amp;#39;ve encountered a NEWLINE after its signature. */&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async_def_nl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NEWLINE&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;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, &lt;code&gt;NEWLINE&lt;/code&gt; is a token, with a value defined in &lt;code&gt;Include/token.h&lt;/code&gt;. All tokens are constant &lt;code&gt;int&lt;/code&gt; values, and the &lt;code&gt;Include/token.h&lt;/code&gt; file was generated earlier when we ran &lt;code&gt;make regen-grammar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;node&lt;/code&gt; type returned by &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Parser/parsetok.c#L163&quot;&gt;&lt;code&gt;PyParser_ParseFileObject()&lt;/code&gt;&lt;/a&gt; is going to be essential for the next stage, converting a parse tree into an Abstract-Syntax-Tree (AST):&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_node&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;short&lt;/span&gt;               &lt;span class=&quot;n&quot;&gt;n_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;                &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;n_lineno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;n_col_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;n_nchildren&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_node&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;n_end_lineno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;n_end_col_offset&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;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since the CST is a tree of syntax, token IDs, and symbols, it would be difficult for the compiler to make quick decisions based on the Python language.&lt;/p&gt;
&lt;p&gt;That is why the next stage is to convert the CST into an AST, a much higher-level structure. This task is performed by the &lt;code&gt;Python/ast.c&lt;/code&gt; module, which has both a C and Python API.&lt;/p&gt;
&lt;p&gt;Before you jump into the AST, there is a way to access the output from the parser stage. CPython has a standard library module &lt;code&gt;parser&lt;/code&gt;, which exposes the C functions with a Python API.&lt;/p&gt;
&lt;p&gt;The module is documented as an implementation detail of CPython so that you won&amp;rsquo;t see it in other Python interpreters. Also the output from the functions is not that easy to read.&lt;/p&gt;
&lt;p&gt;The output will be in the numeric form, using the token and symbol numbers generated by the &lt;code&gt;make regen-grammar&lt;/code&gt; stage, stored in &lt;code&gt;Include/token.h&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;pprint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;parser&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a + 1&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;pprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st2list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[258,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; [332,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  [306,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   [310,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [311,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;     [312,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;      [313,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [316,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;        [317,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;         [318,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;          [319,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           [320,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            [321, [322, [323, [324, [325, [1, &amp;#39;a&amp;#39;]]]]]],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            [14, &amp;#39;+&amp;#39;],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            [321, [322, [323, [324, [325, [2, &amp;#39;1&amp;#39;]]]]]]]]]]]]]]]]],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; [4, &amp;#39;&amp;#39;],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; [0, &amp;#39;&amp;#39;]]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To make it easier to understand, you can take all the numbers in the &lt;code&gt;symbol&lt;/code&gt; and &lt;code&gt;token&lt;/code&gt; modules, put them into a dictionary and recursively replace the values in the output of &lt;code&gt;parser.st2list()&lt;/code&gt; with the names:&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;symbol&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;token&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;parser&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lex&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;n&quot;&gt;symbols&lt;/span&gt; &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;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__dict__&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tokens&lt;/span&gt; &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;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__dict__&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;lexicon&lt;/span&gt; &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;n&quot;&gt;symbols&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;tokens&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&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;n&quot;&gt;st_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st2list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&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;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&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;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&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;n&quot;&gt;r&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;replace&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;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;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lexicon&lt;/span&gt;&lt;span class=&quot;p&quot;&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;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lexicon&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;else&lt;/span&gt;&lt;span class=&quot;p&quot;&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;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;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can run &lt;code&gt;lex()&lt;/code&gt; with a simple expression, like &lt;code&gt;a + 1&lt;/code&gt; to see how this is represented as a parser-tree:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a + 1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;[&amp;#39;eval_input&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; [&amp;#39;testlist&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  [&amp;#39;test&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   [&amp;#39;or_test&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [&amp;#39;and_test&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;     [&amp;#39;not_test&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;      [&amp;#39;comparison&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       [&amp;#39;expr&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;        [&amp;#39;xor_expr&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;         [&amp;#39;and_expr&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;          [&amp;#39;shift_expr&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           [&amp;#39;arith_expr&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            [&amp;#39;term&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             [&amp;#39;factor&amp;#39;, [&amp;#39;power&amp;#39;, [&amp;#39;atom_expr&amp;#39;, [&amp;#39;atom&amp;#39;, [&amp;#39;NAME&amp;#39;, &amp;#39;a&amp;#39;]]]]]],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            [&amp;#39;PLUS&amp;#39;, &amp;#39;+&amp;#39;],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            [&amp;#39;term&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             [&amp;#39;factor&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;              [&amp;#39;power&amp;#39;, [&amp;#39;atom_expr&amp;#39;, [&amp;#39;atom&amp;#39;, [&amp;#39;NUMBER&amp;#39;, &amp;#39;1&amp;#39;]]]]]]]]]]]]]]]]],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; [&amp;#39;NEWLINE&amp;#39;, &amp;#39;&amp;#39;],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; [&amp;#39;ENDMARKER&amp;#39;, &amp;#39;&amp;#39;]]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the output, you can see the symbols in lowercase, such as &lt;code&gt;&#39;test&#39;&lt;/code&gt; and the tokens in uppercase, such as &lt;code&gt;&#39;NUMBER&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;abstract-syntax-trees&quot;&gt;Abstract Syntax Trees&lt;/h3&gt;
&lt;p&gt;The next stage in the CPython interpreter is to convert the CST generated by the parser into something more logical that can be executed. The structure is a higher-level representation of the code, called an Abstract Syntax Tree (AST).&lt;/p&gt;
&lt;p&gt;ASTs are produced inline with the CPython interpreter process, but you can also generate them in both Python using the &lt;code&gt;ast&lt;/code&gt; module in the Standard Library as well as through the C API.&lt;/p&gt;
&lt;p&gt;Before diving into the C implementation of the AST, it would be useful to understand what an AST looks like for a simple piece of Python code.&lt;/p&gt;
&lt;p&gt;To do this, here&amp;rsquo;s a simple app called &lt;code&gt;instaviz&lt;/code&gt; for this tutorial. It displays the AST and bytecode instructions (which we&amp;rsquo;ll cover later) in a Web UI.&lt;/p&gt;
&lt;p&gt;To install &lt;code&gt;instaviz&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 instaviz
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, open up a REPL by running &lt;code&gt;python&lt;/code&gt; at the command line with no 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;instaviz&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;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       a = 1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       b = a + 1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       return b&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instaviz&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;n&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll see a notification on the command-line that a web server has started on port &lt;code&gt;8080&lt;/code&gt;. If you were using that port for something else, you can change it by calling &lt;code&gt;instaviz.show(example, port=9090)&lt;/code&gt; or another port number.&lt;/p&gt;
&lt;p&gt;In the web browser, you can see the detailed breakdown of your function:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/screenshot.e148c89e3a9a.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/screenshot.e148c89e3a9a.png&quot; width=&quot;4802&quot; height=&quot;2566&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/screenshot.e148c89e3a9a.png&amp;amp;w=1200&amp;amp;sig=eeb7b21839b90e3726ea5db7bfa0aac05730b1fe 1200w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/screenshot.e148c89e3a9a.png&amp;amp;w=2401&amp;amp;sig=aed4aed922bbe4ef9c665a90c9244ebaa950e032 2401w, https://files.realpython.com/media/screenshot.e148c89e3a9a.png 4802w&quot; sizes=&quot;75vw&quot; alt=&quot;Instaviz screenshot&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The bottom left graph is the function you declared in REPL, represented as an Abstract Syntax Tree. Each node in the tree is an AST type. They are found in the &lt;code&gt;ast&lt;/code&gt; module, and all inherit from &lt;code&gt;_ast.AST&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Some of the nodes have properties which link them to child nodes, unlike the CST, which has a generic child node property. &lt;/p&gt;
&lt;p&gt;For example, if you click on the Assign node in the center, this links to the line &lt;code&gt;b = a + 1&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.17_pm.a5df8d873988.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-75&quot; src=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.17_pm.a5df8d873988.png&quot; width=&quot;2226&quot; height=&quot;1596&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.17_pm.a5df8d873988.png&amp;amp;w=556&amp;amp;sig=6a6f30034c85f411bd6c159df8aef50e899dda9c 556w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.17_pm.a5df8d873988.png&amp;amp;w=1113&amp;amp;sig=1b85cbf0bec4b114ef52d8a7bcdbfa08a1519237 1113w, https://files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.17_pm.a5df8d873988.png 2226w&quot; sizes=&quot;75vw&quot; alt=&quot;Instaviz screenshot 2&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It has two properties:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;targets&lt;/code&gt;&lt;/strong&gt; is a list of names to assign. It is a list because you can assign to multiple variables with a single expression using unpacking&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt; is the value to assign, which in this case is a &lt;code&gt;BinOp&lt;/code&gt; statement, &lt;code&gt;a + 1&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you click on the &lt;code&gt;BinOp&lt;/code&gt; statement, it shows the properties of relevance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;left&lt;/code&gt;:&lt;/strong&gt; the node to the left of the operator&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;op&lt;/code&gt;:&lt;/strong&gt; the operator, in this case, an &lt;code&gt;Add&lt;/code&gt; node (&lt;code&gt;+&lt;/code&gt;) for addition&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;right&lt;/code&gt;:&lt;/strong&gt; the node to the right of the operator&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.37_pm.21a11b49a820.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-75&quot; src=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.37_pm.21a11b49a820.png&quot; width=&quot;1708&quot; height=&quot;932&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.37_pm.21a11b49a820.png&amp;amp;w=427&amp;amp;sig=381d8bee4cc98dc98031abc6bc34ec376fd452b7 427w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.37_pm.21a11b49a820.png&amp;amp;w=854&amp;amp;sig=ccc0b88e9d762b2298a33ca2a03e826ee13f4193 854w, https://files.realpython.com/media/Screen_Shot_2019-03-19_at_1.24.37_pm.21a11b49a820.png 1708w&quot; sizes=&quot;75vw&quot; alt=&quot;Instaviz screenshot 3&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Compiling an AST in C is not a straightforward task, so the &lt;code&gt;Python/ast.c&lt;/code&gt; module is over 5000 lines of code.&lt;/p&gt;
&lt;p&gt;There are a few entry points, forming part of the AST&amp;rsquo;s public API. In the last section on the lexer and parser, you stopped when you&amp;rsquo;d reached the call to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L772&quot;&gt;&lt;code&gt;PyAST_FromNodeObject()&lt;/code&gt;&lt;/a&gt;. By this stage, the Python interpreter process had created a CST in the format of &lt;code&gt;node *&lt;/code&gt; tree.&lt;/p&gt;
&lt;p&gt;Jumping then into &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L772&quot;&gt;&lt;code&gt;PyAST_FromNodeObject()&lt;/code&gt;&lt;/a&gt; inside &lt;code&gt;Python/ast.c&lt;/code&gt;, you can see it receives the &lt;code&gt;node *&lt;/code&gt; tree, the filename, compiler flags, and the &lt;code&gt;PyArena&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The return type from this function is &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/ast.h#L10&quot;&gt;&lt;code&gt;mod_ty&lt;/code&gt;&lt;/a&gt;, defined in &lt;code&gt;Include/Python-ast.h&lt;/code&gt;. &lt;code&gt;mod_ty&lt;/code&gt; is a container structure for one of the 5 module types in Python:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Module&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Interactive&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Expression&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FunctionType&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Suite&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In &lt;code&gt;Include/Python-ast.h&lt;/code&gt; you can see that an &lt;code&gt;Expression&lt;/code&gt; type requires a field &lt;code&gt;body&lt;/code&gt;, which is an &lt;code&gt;expr_ty&lt;/code&gt; type. The &lt;code&gt;expr_ty&lt;/code&gt; type is also defined in &lt;code&gt;Include/Python-ast.h&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_mod_kind&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module_kind&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;Interactive_kind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Expression_kind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;FunctionType_kind&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;n&quot;&gt;Suite_kind&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;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_mod&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_mod_kind&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;asdl_seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;asdl_seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type_ignores&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;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;asdl_seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&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;Interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;expr_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&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;Expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;asdl_seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argtypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;expr_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returns&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;FunctionType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;asdl_seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&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;Suite&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;v&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 AST types are all listed in &lt;code&gt;Parser/Python.asdl&lt;/code&gt;. You will see the module types, statement types, expression types, operators, and comprehensions all listed. The names of the types in this document relate to the classes generated by the AST and the same classes named in the &lt;code&gt;ast&lt;/code&gt; standard module library.&lt;/p&gt;
&lt;p&gt;The parameters and names in &lt;code&gt;Include/Python-ast.h&lt;/code&gt; correlate directly to those specified in &lt;code&gt;Parser/Python.asdl&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;-- ASDL&amp;#39;s 5 builtin types are:
-- identifier, int, string, object, constant

module Python
{
    mod = Module(stmt* body, type_ignore *type_ignores)
        | Interactive(stmt* body)
&lt;span class=&quot;hll&quot;&gt;        | Expression(expr body)
&lt;/span&gt;        | FunctionType(expr* argtypes, expr returns)
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The C header file and structures are there so that the &lt;code&gt;Python/ast.c&lt;/code&gt; program can quickly generate the structures with pointers to the relevant data.&lt;/p&gt;
&lt;p&gt;Looking at &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L772&quot;&gt;&lt;code&gt;PyAST_FromNodeObject()&lt;/code&gt;&lt;/a&gt; you can see that it is essentially a &lt;code&gt;switch&lt;/code&gt; statement around the result from &lt;code&gt;TYPE(n)&lt;/code&gt;. &lt;code&gt;TYPE()&lt;/code&gt; is one of the core functions used by the AST to determine what type a node in the concrete syntax tree is. In the case of &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L772&quot;&gt;&lt;code&gt;PyAST_FromNodeObject()&lt;/code&gt;&lt;/a&gt; it&amp;rsquo;s just looking at the first node, so it can only be one of the module types defined as &lt;code&gt;Module&lt;/code&gt;, &lt;code&gt;Interactive&lt;/code&gt;, &lt;code&gt;Expression&lt;/code&gt;, &lt;code&gt;FunctionType&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The result of &lt;code&gt;TYPE()&lt;/code&gt; will be either a symbol or token type, which we&amp;rsquo;re very familiar with by this stage.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;file_input&lt;/code&gt;, the results should be a &lt;code&gt;Module&lt;/code&gt;. Modules are a series of statements, of which there are a few types. The logic to traverse the children of &lt;code&gt;n&lt;/code&gt; and create statement nodes is within &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L4512&quot;&gt;&lt;code&gt;ast_for_stmt()&lt;/code&gt;&lt;/a&gt;. This function is called either once, if there is only 1 statement in the module, or in a loop if there are many. The resulting &lt;code&gt;Module&lt;/code&gt; is then returned with the &lt;code&gt;PyArena&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;eval_input&lt;/code&gt;, the result should be an &lt;code&gt;Expression&lt;/code&gt;. The result from &lt;code&gt;CHILD(n ,0)&lt;/code&gt;, which is the first child of &lt;code&gt;n&lt;/code&gt; is passed to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L3246&quot;&gt;&lt;code&gt;ast_for_testlist()&lt;/code&gt;&lt;/a&gt; which returns an &lt;code&gt;expr_ty&lt;/code&gt; type. This &lt;code&gt;expr_ty&lt;/code&gt; is sent to &lt;code&gt;Expression()&lt;/code&gt; with the PyArena to create an expression node, and then passed back as a result:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod_ty&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyAST_FromNodeObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                     &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyArena&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arena&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;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;file_input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_Py_asdl_seq_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&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;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;0&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;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;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;ch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHILD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&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;TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ch&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;NEWLINE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;REQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ch&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;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;                    &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ast_for_stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ch&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;asdl_seq_SET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;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;ch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHILD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ch&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;REQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simple_stmt&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&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;n&quot;&gt;j&lt;/span&gt;&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;hll&quot;&gt;                        &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ast_for_stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHILD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;asdl_seq_SET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;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;cm&quot;&gt;/* Type ignores are stored under the ENDMARKER in file_input. */&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;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type_ignores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;eval_input&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;expr_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;testlist_ast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;cm&quot;&gt;/* XXX Why not comp_for here? */&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;            &lt;span class=&quot;n&quot;&gt;testlist_ast&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ast_for_testlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHILD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;testlist_ast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&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;res&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;testlist_ast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;break&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;single_input&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;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;func_type_input&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&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;Inside the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L4512&quot;&gt;&lt;code&gt;ast_for_stmt()&lt;/code&gt;&lt;/a&gt; function, there is another &lt;code&gt;switch&lt;/code&gt; statement for each possible statement type (&lt;code&gt;simple_stmt&lt;/code&gt;, &lt;code&gt;compound_stmt&lt;/code&gt;, and so on) and the code to determine the arguments to the node class.&lt;/p&gt;
&lt;p&gt;One of the simpler functions is for the power expression, i.e., &lt;code&gt;2**4&lt;/code&gt; is 2 to the power of 4. This function starts by getting the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ast.c#L2770&quot;&gt;&lt;code&gt;ast_for_atom_expr()&lt;/code&gt;&lt;/a&gt;, which is the number &lt;code&gt;2&lt;/code&gt; in our example, then if that has one child, it returns the atomic expression. If it has more than one child, it will get the right-hand (the number &lt;code&gt;4&lt;/code&gt;) and return a &lt;code&gt;BinOp&lt;/code&gt; (binary operation) with the operator as &lt;code&gt;Pow&lt;/code&gt; (power), the left hand of &lt;code&gt;e&lt;/code&gt; (2), and the right hand of &lt;code&gt;f&lt;/code&gt; (4):&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr_ty&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;ast_for_power&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiling&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* power: atom trailer* (&amp;#39;**&amp;#39; factor)*&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expr_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;REQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;power&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ast_for_atom_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHILD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;NCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CHILD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;factor&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;expr_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ast_for_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHILD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&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;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BinOp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Pow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LINENO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_col_offset&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;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_end_lineno&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;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_end_col_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&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;You can see the result of this if you send a short function to the &lt;code&gt;instaviz&lt;/code&gt; module:&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;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       2**4&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;instaviz&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instaviz&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;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-19_at_5.34.51_pm.c3a1e8d717f5.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-75&quot; src=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-19_at_5.34.51_pm.c3a1e8d717f5.png&quot; width=&quot;1708&quot; height=&quot;1094&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-19_at_5.34.51_pm.c3a1e8d717f5.png&amp;amp;w=427&amp;amp;sig=68167794b71cec6447aa8fcb4d22ca738a2e2ce4 427w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-19_at_5.34.51_pm.c3a1e8d717f5.png&amp;amp;w=854&amp;amp;sig=feeef6a7ce0b14d39c57956f77320125bcce43bf 854w, https://files.realpython.com/media/Screen_Shot_2019-03-19_at_5.34.51_pm.c3a1e8d717f5.png 1708w&quot; sizes=&quot;75vw&quot; alt=&quot;Instaviz screenshot 4&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the UI you can also see the corresponding properties:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-19_at_5.36.34_pm.0067235460de.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-75&quot; src=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-19_at_5.36.34_pm.0067235460de.png&quot; width=&quot;1708&quot; height=&quot;630&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-19_at_5.36.34_pm.0067235460de.png&amp;amp;w=427&amp;amp;sig=91663308ef854874e262756b2a28e598d263fff5 427w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-19_at_5.36.34_pm.0067235460de.png&amp;amp;w=854&amp;amp;sig=fbfcdd33bcf685f91ebe0559b4135ead2b296d7e 854w, https://files.realpython.com/media/Screen_Shot_2019-03-19_at_5.36.34_pm.0067235460de.png 1708w&quot; sizes=&quot;75vw&quot; alt=&quot;Instaviz screenshot 5&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In summary, each statement type and expression has a corresponding &lt;code&gt;ast_for_*()&lt;/code&gt; function to create it. The arguments are defined in &lt;code&gt;Parser/Python.asdl&lt;/code&gt; and exposed via the &lt;code&gt;ast&lt;/code&gt; module in the standard library. If an expression or statement has children, then it will call the corresponding &lt;code&gt;ast_for_*&lt;/code&gt; child function in a depth-first traversal.&lt;/p&gt;
&lt;h3 id=&quot;conclusion_1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;CPython&amp;rsquo;s versatility and low-level execution API make it the ideal candidate for an embedded scripting engine. You will see CPython used in many UI applications, such as Game Design, 3D graphics and system automation. &lt;/p&gt;
&lt;p&gt;The interpreter process is flexible and efficient, and now you have an understanding of how it works you&amp;rsquo;re ready to understand the compiler.&lt;/p&gt;
&lt;h2 h1=&quot;h1&quot; id=&quot;part-3-the-cpython-compiler-and-execution-loop&quot;&gt;Part 3: The CPython Compiler and Execution Loop&lt;/h2&gt;
&lt;p&gt;In Part 2, you saw how the CPython interpreter takes an input, such as a file or string, and converts it into a logical Abstract Syntax Tree. We&amp;rsquo;re still not at the stage where this code can be executed. Next, we have to go deeper to convert the Abstract Syntax Tree into a set of sequential commands that the CPU can understand. &lt;/p&gt;
&lt;h3 id=&quot;compiling&quot;&gt;Compiling&lt;/h3&gt;
&lt;p&gt;Now the interpreter has an AST with the properties required for each of the operations, functions, classes, and namespaces. It is the job of the compiler to turn the AST into something the CPU can understand.&lt;/p&gt;
&lt;p&gt;This compilation task is split into 2 parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Traverse the tree and create a control-flow-graph, which represents the logical sequence for execution&lt;/li&gt;
&lt;li&gt;Convert the nodes in the CFG to smaller, executable statements, known as byte-code&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Earlier, we were looking at how files are executed, and the &lt;code&gt;PyRun_FileExFlags()&lt;/code&gt; function in &lt;code&gt;Python/pythonrun.c&lt;/code&gt;. Inside this function, we converted the &lt;code&gt;FILE&lt;/code&gt; handle into a &lt;code&gt;mod&lt;/code&gt;, of type &lt;code&gt;mod_ty&lt;/code&gt;. This task was completed by &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1369&quot;&gt;&lt;code&gt;PyParser_ASTFromFileObject()&lt;/code&gt;&lt;/a&gt;, which in turns calls the &lt;code&gt;tokenizer&lt;/code&gt;, &lt;code&gt;parser-tokenizer&lt;/code&gt; and then the AST:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyRun_FileExFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;closeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&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;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyParser_ASTFromFileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&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;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;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The resulting module from the call to is sent to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1125&quot;&gt;&lt;code&gt;run_mod()&lt;/code&gt;&lt;/a&gt; still in &lt;code&gt;Python/pythonrun.c&lt;/code&gt;. This is a small function that gets a &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/code.h#L69&quot;&gt;&lt;code&gt;PyCodeObject&lt;/code&gt;&lt;/a&gt; from &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L312&quot;&gt;&lt;code&gt;PyAST_CompileObject()&lt;/code&gt;&lt;/a&gt; and sends it on to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1094&quot;&gt;&lt;code&gt;run_eval_code_obj()&lt;/code&gt;&lt;/a&gt;. You will tackle &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1094&quot;&gt;&lt;code&gt;run_eval_code_obj()&lt;/code&gt;&lt;/a&gt; in the next section:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;run_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyArena&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arena&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;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyAST_CompileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;PySys_Audit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;exec&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;O&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;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;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_eval_code_obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&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;v&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 &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L312&quot;&gt;&lt;code&gt;PyAST_CompileObject()&lt;/code&gt;&lt;/a&gt; function is the main entry point to the CPython compiler. It takes a Python module as its primary argument, along with the name of the file, the globals, locals, and the &lt;code&gt;PyArena&lt;/code&gt; all created earlier in the interpreter process.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re starting to get into the guts of the CPython compiler now, with decades of development and Computer Science theory behind it. Don&amp;rsquo;t be put off by the language. Once we break down the compiler into logical steps, it&amp;rsquo;ll make sense.&lt;/p&gt;
&lt;p&gt;Before the compiler starts, a global compiler state is created. This type, &lt;code&gt;compiler&lt;/code&gt; is defined in &lt;code&gt;Python/compile.c&lt;/code&gt; and contains properties used by the compiler to remember the compiler flags, the stack, and the &lt;code&gt;PyArena&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symtable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyFutureFeatures&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_future&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* pointer to module&amp;#39;s __future__ */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_optimize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;              &lt;span class=&quot;cm&quot;&gt;/* optimization level */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;cm&quot;&gt;/* true if in interactive mode */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_nestlevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_do_not_emit_bytecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/* The compiler won&amp;#39;t emit any bytecode&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                    if this value is different from zero.&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                    This can be used to temporarily visit&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                    nodes without emitting bytecode to&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                    check only errors. */&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_const_cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;cm&quot;&gt;/* Python dict holding all constants,&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                    including names tuple */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler_unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* compiler state for current block */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;cm&quot;&gt;/* Python list holding compiler_unit ptrs */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyArena&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;cm&quot;&gt;/* pointer to memory allocation arena */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inside &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L312&quot;&gt;&lt;code&gt;PyAST_CompileObject()&lt;/code&gt;&lt;/a&gt;, there are 11 main steps happening:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create an empty &lt;code&gt;__doc__&lt;/code&gt; property to the module if it doesn&amp;rsquo;t exist.&lt;/li&gt;
&lt;li&gt;Create an empty &lt;code&gt;__annotations__&lt;/code&gt; property to the module if it doesn&amp;rsquo;t exist.&lt;/li&gt;
&lt;li&gt;Set the filename of the global compiler state to the filename argument.&lt;/li&gt;
&lt;li&gt;Set the memory allocation arena for the compiler to the one used by the interpreter.&lt;/li&gt;
&lt;li&gt;Copy any &lt;code&gt;__future__&lt;/code&gt; flags in the module to the future flags in the compiler.&lt;/li&gt;
&lt;li&gt;Merge runtime flags provided by the command-line or environment variables.&lt;/li&gt;
&lt;li&gt;Enable any &lt;code&gt;__future__&lt;/code&gt; features in the compiler.&lt;/li&gt;
&lt;li&gt;Set the optimization level to the provided argument, or default.&lt;/li&gt;
&lt;li&gt;Build a symbol table from the module object.&lt;/li&gt;
&lt;li&gt;Run the compiler with the compiler state and return the code object.&lt;/li&gt;
&lt;li&gt;Free any allocated memory by the compiler.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyAST_CompileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;optimize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyArena&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arena&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;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyCompilerFlags&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;local_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyCompilerFlags_INIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_PyInterpreterState_GET_UNSAFE&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;config&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;if&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;__doc__&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;__doc__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyUnicode_InternFromString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;__doc__&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__doc__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;k&quot;&gt;if&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;__annotations__&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&gt;        &lt;span class=&quot;n&quot;&gt;__annotations__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyUnicode_InternFromString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;__annotations__&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__annotations__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&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;compiler_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;Py_INCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_arena&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_future&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyFuture_FromASTObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_future&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finally&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&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;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local_flags&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&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;merged&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ff_features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cf_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ff_features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cf_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merged&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;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_optimize&lt;/span&gt; &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;optimize&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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;optimization_level&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;optimize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_nestlevel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_do_not_emit_bytecode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_PyAST_Optimize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_optimize&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;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PySymtable_BuildObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_future&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;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&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;PyErr_Occurred&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_SystemError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;no symtable&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

 &lt;span class=&quot;nl&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;compiler_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyErr_Occurred&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;co&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;h4 id=&quot;future-flags-and-compiler-flags&quot;&gt;Future Flags and Compiler Flags&lt;/h4&gt;
&lt;p&gt;Before the compiler runs, there are two types of flags to toggle the features inside the compiler. These come from two places:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The interpreter state, which may have been command-line options, set in &lt;code&gt;pyconfig.h&lt;/code&gt; or via environment variables&lt;/li&gt;
&lt;li&gt;The use of &lt;code&gt;__future__&lt;/code&gt; statements inside the actual source code of the module&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To distinguish the two types of flags, think that the &lt;code&gt;__future__&lt;/code&gt; flags are required because of the syntax or features in that specific module. For example, Python 3.7 introduced delayed evaluation of type hints through the &lt;code&gt;annotations&lt;/code&gt; future flag:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;__future__&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;annotations&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code after this statement might use unresolved type hints, so the &lt;code&gt;__future__&lt;/code&gt; statement is required. Otherwise, the module wouldn&amp;rsquo;t import. It would be unmaintainable to manually request that the person importing the module enable this specific compiler flag.&lt;/p&gt;
&lt;p&gt;The other compiler flags are specific to the environment, so they might change the way the code executes or the way the compiler runs, but they shouldn&amp;rsquo;t link to the source in the same way that &lt;code&gt;__future__&lt;/code&gt; statements do.&lt;/p&gt;
&lt;p&gt;One example of a compiler flag would be the &lt;a href=&quot;https://docs.python.org/3/using/cmdline.html#cmdoption-o&quot;&gt;&lt;code&gt;-O&lt;/code&gt; flag for optimizing the use of &lt;code&gt;assert&lt;/code&gt; statements&lt;/a&gt;. This flag disables any &lt;code&gt;assert&lt;/code&gt; statements, which may have been put in the code for &lt;a href=&quot;https://realpython.com/python-debugging-pdb/&quot;&gt;debugging purposes&lt;/a&gt;.
It can also be enabled with the &lt;code&gt;PYTHONOPTIMIZE=1&lt;/code&gt; environment variable setting.&lt;/p&gt;
&lt;h4 id=&quot;symbol-tables&quot;&gt;Symbol Tables&lt;/h4&gt;
&lt;p&gt;In &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L312&quot;&gt;&lt;code&gt;PyAST_CompileObject()&lt;/code&gt;&lt;/a&gt; there was a reference to a &lt;code&gt;symtable&lt;/code&gt; and a call to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/symtable.c#L262&quot;&gt;&lt;code&gt;PySymtable_BuildObject()&lt;/code&gt;&lt;/a&gt; with the module to be executed.&lt;/p&gt;
&lt;p&gt;The purpose of the symbol table is to provide a list of namespaces, globals, and locals for the compiler to use for referencing and resolving scopes.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;symtable&lt;/code&gt; structure in &lt;code&gt;Include/symtable.h&lt;/code&gt; is well documented, so it&amp;rsquo;s clear what each of the fields is for. There should be one symtable instance for the compiler, so namespacing becomes essential. &lt;/p&gt;
&lt;p&gt;If you create a function called &lt;code&gt;resolve_names()&lt;/code&gt; in one module and declare another function with the same name in another module, you want to be sure which one is called. The symtable serves this purpose, as well as ensuring that variables declared within a narrow scope don&amp;rsquo;t automatically become globals (after all, this isn&amp;rsquo;t JavaScript):&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symtable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;cm&quot;&gt;/* name of file being compiled,&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                       decoded from the filesystem encoding */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_symtable_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* current symbol table entry */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_symtable_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* symbol table entry for module */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;cm&quot;&gt;/* dict: map AST node addresses&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                     *       to symbol table entries */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;             &lt;span class=&quot;cm&quot;&gt;/* list: stack of namespace info */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_global&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;cm&quot;&gt;/* borrowed ref to st_top-&amp;gt;ste_symbols */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st_nblocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                 &lt;span class=&quot;cm&quot;&gt;/* number of blocks used. kept for&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                       consistency with the corresponding&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                       compiler structure */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_private&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;cm&quot;&gt;/* name of current class or NULL */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyFutureFeatures&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_future&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* module&amp;#39;s future features that affect&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;                                       the symbol table */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recursion_depth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;cm&quot;&gt;/* current recursion depth */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recursion_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;cm&quot;&gt;/* recursion limit */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Some of the symbol table API is exposed via &lt;a href=&quot;https://docs.python.org/3/library/symtable.html&quot;&gt;the &lt;code&gt;symtable&lt;/code&gt; module&lt;/a&gt; in the standard library. You can provide an expression or a module an receive a &lt;code&gt;symtable.SymbolTable&lt;/code&gt; instance.&lt;/p&gt;
&lt;p&gt;You can provide a string with a Python expression and the &lt;code&gt;compile_type&lt;/code&gt; of &lt;code&gt;&quot;eval&quot;&lt;/code&gt;, or a module, function or class, and the &lt;code&gt;compile_mode&lt;/code&gt; of &lt;code&gt;&quot;exec&quot;&lt;/code&gt; to get a symbol table.&lt;/p&gt;
&lt;p&gt;Looping over the elements in the table we can see some of the public and private fields and their types:&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;symtable&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symtable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;b + 1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;test.py&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compile_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;eval&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;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__dict__&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_symbols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[{&amp;#39;_Symbol__name&amp;#39;: &amp;#39;b&amp;#39;, &amp;#39;_Symbol__flags&amp;#39;: 6160, &amp;#39;_Symbol__scope&amp;#39;: 3, &amp;#39;_Symbol__namespaces&amp;#39;: ()}]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The C code behind this is all within &lt;code&gt;Python/symtable.c&lt;/code&gt; and the primary interface is the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/symtable.c#L262&quot;&gt;&lt;code&gt;PySymtable_BuildObject()&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;
&lt;p&gt;Similar to the top-level AST function we covered earlier, the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/symtable.c#L262&quot;&gt;&lt;code&gt;PySymtable_BuildObject()&lt;/code&gt;&lt;/a&gt; function switches between the &lt;code&gt;mod_ty&lt;/code&gt; possible types (Module, Expression, Interactive, Suite, FunctionType), and visits each of the statements inside them.&lt;/p&gt;
&lt;p&gt;Remember, &lt;code&gt;mod_ty&lt;/code&gt; is an AST instance, so the will now recursively explore the nodes and branches of the tree and add entries to the symtable:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symtable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PySymtable_BuildObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyFutureFeatures&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;future&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;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symtable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symtable_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;asdl_seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyThreadState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recursion_limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_GetRecursionLimit&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;st&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_top&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Module_kind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&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;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;0&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asdl_seq_LEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seq&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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symtable_visit_stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmt_ty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asdl_seq_GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seq&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;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Expression_kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Interactive_kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Suite_kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;FunctionType_kind&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;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;So for a module, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/symtable.c#L262&quot;&gt;&lt;code&gt;PySymtable_BuildObject()&lt;/code&gt;&lt;/a&gt; will loop through each statement in the module and call &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/symtable.c#L1176&quot;&gt;&lt;code&gt;symtable_visit_stmt()&lt;/code&gt;&lt;/a&gt;. The &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/symtable.c#L1176&quot;&gt;&lt;code&gt;symtable_visit_stmt()&lt;/code&gt;&lt;/a&gt; is a huge &lt;code&gt;switch&lt;/code&gt; statement with a case for each statement type (defined in &lt;code&gt;Parser/Python.asdl&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;For each statement type, there is specific logic to that statement type. For example, a function definition has particular logic for:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If the recursion depth is beyond the limit, raise a recursion depth error&lt;/li&gt;
&lt;li&gt;The name of the function to be added as a local variable&lt;/li&gt;
&lt;li&gt;The default values for sequential arguments to be resolved&lt;/li&gt;
&lt;li&gt;The default values for keyword arguments to be resolved &lt;/li&gt;
&lt;li&gt;Any annotations for the arguments or the return type are resolved&lt;/li&gt;
&lt;li&gt;Any function decorators are resolved&lt;/li&gt;
&lt;li&gt;The code block with the contents of the function is visited in &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/symtable.c#L973&quot;&gt;&lt;code&gt;symtable_enter_block()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The arguments are visited&lt;/li&gt;
&lt;li&gt;The body of the function is visited&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you&amp;rsquo;ve ever wondered why Python&amp;rsquo;s default arguments are mutable, the reason is in this function. You can see they are a pointer to the variable in the symtable. No extra work is done to copy any values to an immutable type.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;symtable_visit_stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symtable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recursion_depth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recursion_limit&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;// 1.&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_RecursionError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&amp;quot;maximum recursion depth exceeded during compilation&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;VISIT_QUIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;FunctionDef_kind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symtable_add_def&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&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;n&quot;&gt;DEF_LOCAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// 2.&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;VISIT_QUIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&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;hll&quot;&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;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&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;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                                    &lt;span class=&quot;c1&quot;&gt;// 3.&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;VISIT_SEQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&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;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&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;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kw_defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                                 &lt;span class=&quot;c1&quot;&gt;// 4.&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;VISIT_SEQ_WITH_NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&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;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kw_defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symtable_visit_annotations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// 5.&lt;/span&gt;
&lt;/span&gt;                                        &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;VISIT_QUIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&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;hll&quot;&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;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decorator_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                                    &lt;span class=&quot;c1&quot;&gt;// 6.&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;VISIT_SEQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decorator_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symtable_enter_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&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;c1&quot;&gt;// 7.&lt;/span&gt;
&lt;/span&gt;                                  &lt;span class=&quot;n&quot;&gt;FunctionBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &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;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                  &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;VISIT_QUIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&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;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;VISIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;// 8.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;VISIT_SEQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionDef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                             &lt;span class=&quot;c1&quot;&gt;// 9.&lt;/span&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symtable_exit_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;VISIT_QUIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;ClassDef_kind&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;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Return_kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Delete_kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Assign_kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;AnnAssign_kind&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;Once the resulting symtable has been created, it is sent back to be used for the compiler.&lt;/p&gt;
&lt;h4 id=&quot;core-compilation-process&quot;&gt;Core Compilation Process&lt;/h4&gt;
&lt;p&gt;Now that the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L312&quot;&gt;&lt;code&gt;PyAST_CompileObject()&lt;/code&gt;&lt;/a&gt; has a compiler state, a symtable, and a module in the form of the AST, the actual compilation can begin.&lt;/p&gt;
&lt;p&gt;The purpose of the core compiler is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Convert the state, symtable, and AST into a &lt;a href=&quot;https://en.wikipedia.org/wiki/Control-flow_graph&quot;&gt;Control-Flow-Graph (CFG)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Protect the execution stage from runtime exceptions by catching any logic and code errors and raising them here&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can call the CPython compiler in Python code by calling the built-in function &lt;code&gt;compile()&lt;/code&gt;. It returns a &lt;code&gt;code object&lt;/code&gt; instance:&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;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;b+1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;test.py&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;s1&quot;&gt;&amp;#39;eval&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;code object &amp;lt;module&amp;gt; at 0x10f222780, file &amp;quot;test.py&amp;quot;, line 1&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The same as with the &lt;code&gt;symtable()&lt;/code&gt; function, a simple expression should have a mode of &lt;code&gt;&#39;eval&#39;&lt;/code&gt; and a module, function, or class should have a mode of &lt;code&gt;&#39;exec&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The compiled code can be found in the &lt;code&gt;co_code&lt;/code&gt; property of the code object:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_code&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;e\x00d\x00\x17\x00S\x00&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is also a &lt;code&gt;dis&lt;/code&gt; module in the standard library, which disassembles the bytecode instructions and can print them on the screen or give you a list of &lt;code&gt;Instruction&lt;/code&gt; instances.&lt;/p&gt;
&lt;p&gt;If you import &lt;code&gt;dis&lt;/code&gt; and give the &lt;code&gt;dis()&lt;/code&gt; function the code object&amp;rsquo;s &lt;code&gt;co_code&lt;/code&gt; property it disassembles it and prints the instructions on the REPL:&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;dis&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;          0 LOAD_NAME                0 (0)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;          2 LOAD_CONST               0 (0)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;          4 BINARY_ADD&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;          6 RETURN_VALUE&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;LOAD_NAME&lt;/code&gt;, &lt;code&gt;LOAD_CONST&lt;/code&gt;, &lt;code&gt;BINARY_ADD&lt;/code&gt;, and &lt;code&gt;RETURN_VALUE&lt;/code&gt; are all bytecode instructions. They&amp;rsquo;re called bytecode because, in binary form, they were a byte long. However, since Python 3.6 the storage format was changed to a &lt;code&gt;word&lt;/code&gt;, so now they&amp;rsquo;re technically wordcode, not bytecode.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.python.org/3/library/dis.html#python-bytecode-instructions&quot;&gt;full list of bytecode instructions&lt;/a&gt; is available for each version of Python, and it does change between versions. For example, in Python 3.7, some new bytecode instructions were introduced to speed up execution of specific method calls.&lt;/p&gt;
&lt;p&gt;In an earlier section, we explored the &lt;code&gt;instaviz&lt;/code&gt; package. This included a visualization of the code object type by running the compiler. It also displays the Bytecode operations inside the code objects.&lt;/p&gt;
&lt;p&gt;Execute instaviz again to see the code object and bytecode for a function defined on the REPL:&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;instaviz&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;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       a = 1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       b = a + 1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       return b&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instaviz&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;n&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we now jump into &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L1782&quot;&gt;&lt;code&gt;compiler_mod()&lt;/code&gt;&lt;/a&gt;, a function used to switch to different compiler functions depending on the module type. We&amp;rsquo;ll assume that &lt;code&gt;mod&lt;/code&gt; is a &lt;code&gt;Module&lt;/code&gt;. The module is compiled into the compiler state and then &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L5971&quot;&gt;&lt;code&gt;assemble()&lt;/code&gt;&lt;/a&gt; is run to create a &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/code.h#L69&quot;&gt;&lt;code&gt;PyCodeObject&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The new code object is returned back to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L312&quot;&gt;&lt;code&gt;PyAST_CompileObject()&lt;/code&gt;&lt;/a&gt; and sent on for execution:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;compiler_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&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;n&quot;&gt;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addNone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module&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;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Module_kind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compiler_body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&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&gt;            &lt;span class=&quot;n&quot;&gt;compiler_exit_scope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Interactive_kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Expression_kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Suite_kind&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;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assemble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;compiler_exit_scope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L1743&quot;&gt;&lt;code&gt;compiler_body()&lt;/code&gt;&lt;/a&gt; function has some optimization flags and then loops over each statement in the module and visits it, similar to how the &lt;code&gt;symtable&lt;/code&gt; functions worked:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;compiler_body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asdl_seq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stmt_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;docstring&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;k&quot;&gt;for&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asdl_seq_LEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&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;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;VISIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt&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;stmt_ty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asdl_seq_GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&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&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The statement type is determined through a call to the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/asdl.h#L32&quot;&gt;&lt;code&gt;asdl_seq_GET()&lt;/code&gt;&lt;/a&gt; function, which looks at the AST node&amp;rsquo;s type.&lt;/p&gt;
&lt;p&gt;Through some smart macros, &lt;code&gt;VISIT&lt;/code&gt; calls a function in &lt;code&gt;Python/compile.c&lt;/code&gt; for each statement type:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#define VISIT(C, TYPE, V) {\&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;    if (!compiler_visit_ ## TYPE((C), (V))) \&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;        return 0; \&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For a &lt;code&gt;stmt&lt;/code&gt; (the category for a statement) the compiler will then drop into &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L3310&quot;&gt;&lt;code&gt;compiler_visit_stmt()&lt;/code&gt;&lt;/a&gt; and switch through all of the potential statement types found in &lt;code&gt;Parser/Python.asdl&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;compiler_visit_stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_ssize_t&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;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* Always assign a lineno to the next instruction for a stmt. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_lineno&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_col_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_lineno_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&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;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;FunctionDef_kind&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;compiler_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;ClassDef_kind&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;compiler_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;For_kind&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;compiler_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As an example, let&amp;rsquo;s focus on the &lt;code&gt;For&lt;/code&gt; statement, in Python is the:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# block&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;# optional if iterable is False&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# block&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the statement is a &lt;code&gt;For&lt;/code&gt; type, it calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L2651&quot;&gt;&lt;code&gt;compiler_for()&lt;/code&gt;&lt;/a&gt;. There is an equivalent &lt;code&gt;compiler_*()&lt;/code&gt; function for all of the statement and expression types. The more straightforward types create the bytecode instructions inline, some of the more complex statement types call other functions.&lt;/p&gt;
&lt;p&gt;Many of the statements can have sub-statements. A &lt;code&gt;for&lt;/code&gt; loop has a body, but you can also have complex expressions in the assignment and the iterator.&lt;/p&gt;
&lt;p&gt;The compiler&amp;rsquo;s &lt;code&gt;compiler_&lt;/code&gt; statements sends blocks to the compiler state. These blocks contain instructions, the instruction data structure in &lt;code&gt;Python/compile.c&lt;/code&gt; has the opcode, any arguments, and the target block (if this is a jump instruction), it also contains the line number.&lt;/p&gt;
&lt;p&gt;For jump statements, they can either be absolute or relative jump statements. Jump statements are used to &amp;ldquo;jump&amp;rdquo; from one operation to another. Absolute jump statements specify the exact operation number in the compiled code object, whereas relative jump statements specify the jump target relative to another operation:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;i_jabs&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;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;i_jrel&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;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i_opcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i_oparg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;basicblock_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* target block (if jump instruction) */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i_lineno&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;So a frame block (of type &lt;code&gt;basicblock&lt;/code&gt;), contains the following fields:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;b_list&lt;/code&gt; pointer, the link to a list of blocks for the compiler state&lt;/li&gt;
&lt;li&gt;A list of instructions &lt;code&gt;b_instr&lt;/code&gt;, with both the allocated list size &lt;code&gt;b_ialloc&lt;/code&gt;, and the number used &lt;code&gt;b_iused&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The next block after this one &lt;code&gt;b_next&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Whether the block has been &amp;ldquo;seen&amp;rdquo; by the assembler when traversing depth-first&lt;/li&gt;
&lt;li&gt;If this block has a &lt;code&gt;RETURN_VALUE&lt;/code&gt; opcode (&lt;code&gt;b_return&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The depth of the stack when this block was entered (&lt;code&gt;b_startdepth&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The instruction offset for the assembler&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;basicblock_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* Each basicblock in a compilation unit is linked via b_list in the&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       reverse order that the block are allocated.  b_list points to the next&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       block, not to be confused with b_next, which is next by control flow. */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;basicblock_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* number of instructions used */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b_iused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* length of instruction array (b_instr) */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b_ialloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* pointer to an array of instructions, initially NULL */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_instr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* If b_next is non-NULL, it is a pointer to the next&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       block reached by normal control flow. */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;basicblock_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* b_seen is used to perform a DFS of basicblocks. */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;b_seen&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;cm&quot;&gt;/* b_return is true if a RETURN_VALUE opcode is inserted. */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;b_return&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;cm&quot;&gt;/* depth of stack upon entry of block, computed by stackdepth() */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b_startdepth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* instruction offset for block, computed by assemble_jump_offsets() */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b_offset&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;basicblock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;For&lt;/code&gt; statement is somewhere in the middle in terms of complexity. There are 15 steps in the compilation of a &lt;code&gt;For&lt;/code&gt; statement with the &lt;code&gt;for &amp;lt;target&amp;gt; in &amp;lt;iterator&amp;gt;:&lt;/code&gt; syntax:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new code block called &lt;code&gt;start&lt;/code&gt;, this allocates memory and creates a &lt;code&gt;basicblock&lt;/code&gt; pointer&lt;/li&gt;
&lt;li&gt;Create a new code block called &lt;code&gt;cleanup&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a new code block called &lt;code&gt;end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Push a frame block of type &lt;code&gt;FOR_LOOP&lt;/code&gt; to the stack with &lt;code&gt;start&lt;/code&gt; as the entry block and &lt;code&gt;end&lt;/code&gt; as the exit block&lt;/li&gt;
&lt;li&gt;Visit the iterator expression, which adds any operations for the iterator&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;GET_ITER&lt;/code&gt; operation to the compiler state&lt;/li&gt;
&lt;li&gt;Switch to the &lt;code&gt;start&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;ADDOP_JREL&lt;/code&gt; which calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L1413&quot;&gt;&lt;code&gt;compiler_addop_j()&lt;/code&gt;&lt;/a&gt; to add the &lt;code&gt;FOR_ITER&lt;/code&gt; operation with an argument of the &lt;code&gt;cleanup&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;Visit the &lt;code&gt;target&lt;/code&gt; and add any special code, like tuple unpacking, to the &lt;code&gt;start&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;Visit each statement in the body of the for loop&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;ADDOP_JABS&lt;/code&gt; which calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L1413&quot;&gt;&lt;code&gt;compiler_addop_j()&lt;/code&gt;&lt;/a&gt; to add the &lt;code&gt;JUMP_ABSOLUTE&lt;/code&gt; operation which indicates after the body is executed, jumps back to the start of the loop&lt;/li&gt;
&lt;li&gt;Move to the &lt;code&gt;cleanup&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;Pop the &lt;code&gt;FOR_LOOP&lt;/code&gt; frame block off the stack&lt;/li&gt;
&lt;li&gt;Visit the statements inside the &lt;code&gt;else&lt;/code&gt; section of the for loop&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;end&lt;/code&gt; block&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Referring back to the &lt;code&gt;basicblock&lt;/code&gt; structure. You can see how in the compilation of the for statement, the various blocks are created and pushed into the compiler&amp;rsquo;s frame block and stack:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;compiler_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt_ty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;basicblock&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cleanup&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;end&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;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler_new_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;// 1.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler_new_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;// 2.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler_new_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;// 3.&lt;/span&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;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;hll&quot;&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compiler_push_fblock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FOR_LOOP&lt;/span&gt;&lt;span class=&quot;p&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;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 4.&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;VISIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;For&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;// 5.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;ADDOP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GET_ITER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                                  &lt;span class=&quot;c1&quot;&gt;// 6.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;compiler_use_next_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&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;c1&quot;&gt;// 7.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;ADDOP_JREL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FOR_ITER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                    &lt;span class=&quot;c1&quot;&gt;// 8.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;VISIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;For&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;p&quot;&gt;);&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;// 9.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;VISIT_SEQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;For&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;// 10.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;ADDOP_JABS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JUMP_ABSOLUTE&lt;/span&gt;&lt;span class=&quot;p&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;c1&quot;&gt;// 11.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;compiler_use_next_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;// 12.&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;compiler_pop_fblock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FOR_LOOP&lt;/span&gt;&lt;span class=&quot;p&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;c1&quot;&gt;// 13.&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;VISIT_SEQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;For&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;orelse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;// 14.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;compiler_use_next_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;// 15.&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Depending on the type of operation, there are different arguments required. For example, we used &lt;code&gt;ADDOP_JABS&lt;/code&gt; and &lt;code&gt;ADDOP_JREL&lt;/code&gt; here, which refer to &amp;ldquo;&lt;strong&gt;ADD&lt;/strong&gt; &lt;strong&gt;O&lt;/strong&gt;peration with &lt;strong&gt;J&lt;/strong&gt;ump to a &lt;strong&gt;REL&lt;/strong&gt;ative position&amp;rdquo; and &amp;ldquo;&lt;strong&gt;ADD&lt;/strong&gt; &lt;strong&gt;O&lt;/strong&gt;peration with &lt;strong&gt;J&lt;/strong&gt;ump to an &lt;strong&gt;ABS&lt;/strong&gt;olute position&amp;rdquo;. This is referring to the &lt;code&gt;APPOP_JREL&lt;/code&gt; and &lt;code&gt;ADDOP_JABS&lt;/code&gt; macros which call &lt;code&gt;compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)&lt;/code&gt; and set the &lt;code&gt;absolute&lt;/code&gt; argument to 0 and 1 respectively.&lt;/p&gt;
&lt;p&gt;There are some other macros, like &lt;code&gt;ADDOP_I&lt;/code&gt; calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L1383&quot;&gt;&lt;code&gt;compiler_addop_i()&lt;/code&gt;&lt;/a&gt; which add an operation with an integer argument, or &lt;code&gt;ADDOP_O&lt;/code&gt; calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L1345&quot;&gt;&lt;code&gt;compiler_addop_o()&lt;/code&gt;&lt;/a&gt; which adds an operation with a &lt;code&gt;PyObject&lt;/code&gt; argument. &lt;/p&gt;
&lt;p&gt;Once these stages have completed, the compiler has a list of frame blocks, each containing a list of instructions and a pointer to the next block.&lt;/p&gt;
&lt;h4 id=&quot;assembly&quot;&gt;Assembly&lt;/h4&gt;
&lt;p&gt;With the compiler state, the assembler performs a &amp;ldquo;depth-first-search&amp;rdquo; of the blocks and merge the instructions into a single bytecode sequence. The assembler state is declared in &lt;code&gt;Python/compile.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assembler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_bytecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/* string containing bytecode */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;              &lt;span class=&quot;cm&quot;&gt;/* offset into bytecode */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_nblocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;             &lt;span class=&quot;cm&quot;&gt;/* number of reachable blocks */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;basicblock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_postorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* list of blocks in dfs postorder */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_lnotab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* string containing lnotab */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_lnotab_off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;cm&quot;&gt;/* offset into lnotab */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_lineno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;              &lt;span class=&quot;cm&quot;&gt;/* last lineno of emitted instruction */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_lineno_off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;cm&quot;&gt;/* bytecode offset of last lineno */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;assemble()&lt;/code&gt; function has a few tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Calculate the number of blocks for memory allocation&lt;/li&gt;
&lt;li&gt;Ensure that every block that falls off the end returns &lt;code&gt;None&lt;/code&gt;, this is why every function returns &lt;code&gt;None&lt;/code&gt;, whether or not a &lt;code&gt;return&lt;/code&gt; statement exists&lt;/li&gt;
&lt;li&gt;Resolve any jump statements offsets that were marked as relative&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;dfs()&lt;/code&gt; to perform a depth-first-search of the blocks&lt;/li&gt;
&lt;li&gt;Emit all the instructions to the compiler&lt;/li&gt;
&lt;li&gt;Call &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L5854&quot;&gt;&lt;code&gt;makecode()&lt;/code&gt;&lt;/a&gt; with the compiler state to generate the &lt;code&gt;PyCodeObject&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;assemble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addNone&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;basicblock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&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;entryblock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assembler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&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;n&quot;&gt;nblocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* Make sure every block that falls off the end returns None.&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       XXX NEXT_BLOCK() isn&amp;#39;t quite right, because if the last&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       block ends with a jump or return b_next shouldn&amp;#39;t set.&lt;/span&gt;
&lt;span class=&quot;cm&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_curblock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_return&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;NEXT_BLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;            &lt;span class=&quot;n&quot;&gt;ADDOP_LOAD_CONST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;ADDOP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RETURN_VALUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&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;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;dfs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entryblock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nblocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* Can&amp;#39;t modify the bytecode after computing jump offsets. */&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;assemble_jump_offsets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* Emit code in reverse postorder from dfs. */&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;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;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_nblocks&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;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;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;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_postorder&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&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_iused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assemble_emit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_instr&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&gt;&lt;span class=&quot;hll&quot;&gt;                &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;makecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt; &lt;span class=&quot;nl&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;assemble_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;co&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 depth-first-search is performed by the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L5397&quot;&gt;&lt;code&gt;dfs()&lt;/code&gt;&lt;/a&gt; function in &lt;code&gt;Python/compile.c&lt;/code&gt;, which follows the the &lt;code&gt;b_next&lt;/code&gt; pointers in each of the blocks, marks them as seen by toggling &lt;code&gt;b_seen&lt;/code&gt; and then adds them to the assemblers &lt;code&gt;**a_postorder&lt;/code&gt; list in reverse order.&lt;/p&gt;
&lt;p&gt;The function loops back over the assembler&amp;rsquo;s post-order list and for each block, if it has a jump operation, recursively call &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L5397&quot;&gt;&lt;code&gt;dfs()&lt;/code&gt;&lt;/a&gt; for that jump:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;dfs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;basicblock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assembler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&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;cm&quot;&gt;/* Get rid of recursion for normal control flow.&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       Since the number of blocks is limited, unused space in a_postorder&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       (from a_nblocks to end) can be used as a stack for still not ordered&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;       blocks. */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&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;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_seen&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;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_next&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;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_seen&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;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_nblocks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&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;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_postorder&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;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;n&quot;&gt;b&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;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&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;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_postorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&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;0&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_iused&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;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b_instr&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i_jrel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i_jabs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;dfs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_nblocks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&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;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_postorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_nblocks&lt;/span&gt;&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;n&quot;&gt;b&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;/pre&gt;&lt;/div&gt;

&lt;h4 id=&quot;creating-a-code-object&quot;&gt;Creating a Code Object&lt;/h4&gt;
&lt;p&gt;The task of &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L5854&quot;&gt;&lt;code&gt;makecode()&lt;/code&gt;&lt;/a&gt; is to go through the compiler state, some of the assembler&amp;rsquo;s properties and to put these into a &lt;code&gt;PyCodeObject&lt;/code&gt; by calling &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/codeobject.c#L246&quot;&gt;&lt;code&gt;PyCode_New()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/codeobject.9c054576627c.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/codeobject.9c054576627c.png&quot; width=&quot;201&quot; height=&quot;550&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/codeobject.9c054576627c.png&amp;amp;w=50&amp;amp;sig=9d1c4ff65adb0d6d578b775ca93a88843a3742c1 50w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/codeobject.9c054576627c.png&amp;amp;w=100&amp;amp;sig=076765eedb49d9e4e944629435b5a0fc10942c4c 100w, https://files.realpython.com/media/codeobject.9c054576627c.png 201w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCodeObject structure&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The variable names, constants are put as properties to the code object:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCodeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;makecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compiler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assembler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;consts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;consts_dict_keys_inorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_consts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dict_keys_inorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_names&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;varnames&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dict_keys_inorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_varnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cellvars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dict_keys_inorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_cellvars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;freevars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dict_keys_inorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_freevars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyTuple_GET_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cellvars&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;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_code_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;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;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;bytecode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCode_Optimize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_bytecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;consts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_lnotab&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;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCode_NewWithPosOnlyArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;posonlyargcount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;posorkeywordargcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                   &lt;span class=&quot;n&quot;&gt;posonlyargcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwonlyargcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nlocals_int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                                   &lt;span class=&quot;n&quot;&gt;maxdepth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;consts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                   &lt;span class=&quot;n&quot;&gt;varnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;freevars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cellvars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                   &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u_firstlineno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_lnotab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&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;You may also notice that the bytecode is sent to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/peephole.c#L230&quot;&gt;&lt;code&gt;PyCode_Optimize()&lt;/code&gt;&lt;/a&gt; before it is sent to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/codeobject.c#L106&quot;&gt;&lt;code&gt;PyCode_NewWithPosOnlyArgs()&lt;/code&gt;&lt;/a&gt;. This function is part of the bytecode optimization process in &lt;code&gt;Python/peephole.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The peephole optimizer goes through the bytecode instructions and in certain scenarios, replace them with other instructions. For example, there is an optimizer called &amp;ldquo;constant unfolding&amp;rdquo;, so if you put the following statement into your script:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;mi&quot;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It optimizes that to:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because 1 and 5 are constant values, so the result should always be the same.&lt;/p&gt;
&lt;h4 id=&quot;conclusion_2&quot;&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We can pull together all of these stages with the instaviz module:&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;instaviz&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&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;mi&quot;&gt;1&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;n&quot;&gt;c&lt;/span&gt; &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;4&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;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;c&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;i&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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;c&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;instaviz&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;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Will produce an AST graph:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-20_at_3.18.32_pm.4d9a0ea827ff.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/Screen_Shot_2019-03-20_at_3.18.32_pm.4d9a0ea827ff.png&quot; width=&quot;2788&quot; height=&quot;1554&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-20_at_3.18.32_pm.4d9a0ea827ff.png&amp;amp;w=697&amp;amp;sig=9106a1bc23c5cc07f2ef159968c1ba2155a6562d 697w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-20_at_3.18.32_pm.4d9a0ea827ff.png&amp;amp;w=1394&amp;amp;sig=244bebb56c46d0b1eef97b8332afb6bfaa5e3648 1394w, https://files.realpython.com/media/Screen_Shot_2019-03-20_at_3.18.32_pm.4d9a0ea827ff.png 2788w&quot; sizes=&quot;75vw&quot; alt=&quot;Instaviz screenshot 6&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With bytecode instructions in sequence:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-20_at_3.17.54_pm.6ea8ea532015.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/Screen_Shot_2019-03-20_at_3.17.54_pm.6ea8ea532015.png&quot; width=&quot;2536&quot; height=&quot;1592&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-20_at_3.17.54_pm.6ea8ea532015.png&amp;amp;w=634&amp;amp;sig=f499889305c84679bdf07256f978975bbbc98c03 634w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-20_at_3.17.54_pm.6ea8ea532015.png&amp;amp;w=1268&amp;amp;sig=8d86595bce0f05c8dc45c3db3c0bff9b2d9cb0a9 1268w, https://files.realpython.com/media/Screen_Shot_2019-03-20_at_3.17.54_pm.6ea8ea532015.png 2536w&quot; sizes=&quot;75vw&quot; alt=&quot;Instaviz screenshot 7&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, the code object with the variable names, constants, and binary &lt;code&gt;co_code&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-20_at_3.17.41_pm.231a0678f142.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/Screen_Shot_2019-03-20_at_3.17.41_pm.231a0678f142.png&quot; width=&quot;2098&quot; height=&quot;940&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-20_at_3.17.41_pm.231a0678f142.png&amp;amp;w=524&amp;amp;sig=6daa3f3b9841eabbbf87d73886b81d346cdb33b3 524w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-20_at_3.17.41_pm.231a0678f142.png&amp;amp;w=1049&amp;amp;sig=7b074cc948021547f3da60e6bf0be3747585c6c8 1049w, https://files.realpython.com/media/Screen_Shot_2019-03-20_at_3.17.41_pm.231a0678f142.png 2098w&quot; sizes=&quot;75vw&quot; alt=&quot;Instaviz screenshot 8&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;execution&quot;&gt;Execution&lt;/h3&gt;
&lt;p&gt;In &lt;code&gt;Python/pythonrun.c&lt;/code&gt; we broke out just before the call to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1094&quot;&gt;&lt;code&gt;run_eval_code_obj()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This call takes a code object, either fetched from the marshaled &lt;code&gt;.pyc&lt;/code&gt; file, or compiled through the AST and compiler stages.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/pythonrun.c#L1094&quot;&gt;&lt;code&gt;run_eval_code_obj()&lt;/code&gt;&lt;/a&gt; will pass the globals, locals, &lt;code&gt;PyArena&lt;/code&gt;, and compiled &lt;code&gt;PyCodeObject&lt;/code&gt; to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L716&quot;&gt;&lt;code&gt;PyEval_EvalCode()&lt;/code&gt;&lt;/a&gt; in &lt;code&gt;Python/ceval.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This stage forms the execution component of CPython. Each of the bytecode operations is taken and executed using a &lt;a href=&quot;http://www.cs.uwm.edu/classes/cs315/Bacon/Lecture/HTML/ch10s07.html&quot;&gt;&amp;ldquo;Stack Frame&amp;rdquo; based system&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;What is a Stack Frame?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Stack Frames are a data type used by many runtimes, not just Python, that allows functions to be called and variables to be returned between functions. Stack Frames also contain arguments, local variables, and other state information.&lt;/p&gt;
&lt;p&gt;Typically, a Stack Frame exists for every function call, and they are stacked in sequence. You can see CPython&amp;rsquo;s frame stack anytime an exception is unhandled and the stack is printed on the screen.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L716&quot;&gt;&lt;code&gt;PyEval_EvalCode()&lt;/code&gt;&lt;/a&gt; is the public API for evaluating a code object. The logic for evaluation is split between &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L4045&quot;&gt;&lt;code&gt;_PyEval_EvalCodeWithName()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L745&quot;&gt;&lt;code&gt;_PyEval_EvalFrameDefault()&lt;/code&gt;&lt;/a&gt;, which are both in &lt;code&gt;ceval.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The public API &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L716&quot;&gt;&lt;code&gt;PyEval_EvalCode()&lt;/code&gt;&lt;/a&gt; will construct an execution frame from the top of the stack by calling &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L4045&quot;&gt;&lt;code&gt;_PyEval_EvalCodeWithName()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The construction of the first execution frame has many steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Keyword and positional arguments are resolved.&lt;/li&gt;
&lt;li&gt;The use of &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; in function definitions are resolved.&lt;/li&gt;
&lt;li&gt;Arguments are added as local variables to the scope.&lt;/li&gt;
&lt;li&gt;Co-routines and &lt;a href=&quot;https://realpython.com/introduction-to-python-generators/&quot;&gt;Generators&lt;/a&gt; are created, including the Asynchronous Generators.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The frame object looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/PyFrameObject.8616eee0503e.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/PyFrameObject.8616eee0503e.png&quot; width=&quot;161&quot; height=&quot;408&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/PyFrameObject.8616eee0503e.png&amp;amp;w=40&amp;amp;sig=5c85bcc7939e61d207a19cf82d23cab3f73ec760 40w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/PyFrameObject.8616eee0503e.png&amp;amp;w=80&amp;amp;sig=25333bbe22791650facbac4288bb9f49065fb014 80w, https://files.realpython.com/media/PyFrameObject.8616eee0503e.png 161w&quot; sizes=&quot;75vw&quot; alt=&quot;PyFrameObject structure&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s step through those sequences.&lt;/p&gt;
&lt;h4 id=&quot;1-constructing-thread-state&quot;&gt;1. Constructing Thread State&lt;/h4&gt;
&lt;p&gt;Before a frame can be executed, it needs to be referenced from a thread. CPython can have many threads running at any one time within a single interpreter. An Interpreter state includes a list of those threads as a linked list. The thread structure is called &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/pystate.h#L23&quot;&gt;&lt;code&gt;PyThreadState&lt;/code&gt;&lt;/a&gt;, and there are many references throughout &lt;code&gt;ceval.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is the structure of the thread state object:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/PyThreadState.20467f3689b7.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/PyThreadState.20467f3689b7.png&quot; width=&quot;201&quot; height=&quot;208&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/PyThreadState.20467f3689b7.png&amp;amp;w=50&amp;amp;sig=90efd8d98ffa8ad9ed8b233c1e73fa469e4db4ac 50w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/PyThreadState.20467f3689b7.png&amp;amp;w=100&amp;amp;sig=e5d4a21dbc5cce9c1017a6d1805cf9eedf03ac9c 100w, https://files.realpython.com/media/PyThreadState.20467f3689b7.png 201w&quot; sizes=&quot;75vw&quot; alt=&quot;PyThreadState structure&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;2-constructing-frames&quot;&gt;2. Constructing Frames&lt;/h4&gt;
&lt;p&gt;The input to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L716&quot;&gt;&lt;code&gt;PyEval_EvalCode()&lt;/code&gt;&lt;/a&gt; and therefore &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L4045&quot;&gt;&lt;code&gt;_PyEval_EvalCodeWithName()&lt;/code&gt;&lt;/a&gt; has arguments for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;_co&lt;/code&gt;:&lt;/strong&gt; a &lt;code&gt;PyCodeObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;globals&lt;/code&gt;:&lt;/strong&gt; a &lt;code&gt;PyDict&lt;/code&gt; with variable names as keys and their values&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;locals&lt;/code&gt;:&lt;/strong&gt; a &lt;code&gt;PyDict&lt;/code&gt; with variable names as keys and their values&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The other arguments are optional, and not used for the basic API:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;args&lt;/code&gt;:&lt;/strong&gt; a &lt;code&gt;PyTuple&lt;/code&gt; with positional argument values in order, and &lt;code&gt;argcount&lt;/code&gt; for the number of values&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;kwnames&lt;/code&gt;:&lt;/strong&gt; a list of keyword argument names&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;kwargs&lt;/code&gt;:&lt;/strong&gt; a list of keyword argument values, and &lt;code&gt;kwcount&lt;/code&gt; for the number of them&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;defs&lt;/code&gt;:&lt;/strong&gt; a list of default values for positional arguments, and &lt;code&gt;defcount&lt;/code&gt; for the length&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;kwdefs&lt;/code&gt;:&lt;/strong&gt; a dictionary with the default values for keyword arguments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;closure&lt;/code&gt;:&lt;/strong&gt; a tuple with strings to merge into the code objects &lt;code&gt;co_freevars&lt;/code&gt; field&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;name&lt;/code&gt;:&lt;/strong&gt; the name for this evaluation statement as a string&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;qualname&lt;/code&gt;:&lt;/strong&gt; the qualified name for this evaluation statement as a string&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;_PyEval_EvalCodeWithName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&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;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwstep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwdefs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;closure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qualname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;PyThreadState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyThreadState_GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;globals&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;_PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyExc_SystemError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                         &lt;span class=&quot;s&quot;&gt;&amp;quot;PyEval_EvalCodeEx: NULL globals&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;cm&quot;&gt;/* Create the frame */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyFrame_New_NoTrack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locals&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;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;fastlocals&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_localsplus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;freevars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_localsplus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_nlocals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&quot;3-converting-keyword-parameters-to-a-dictionary&quot;&gt;3. Converting Keyword Parameters to a Dictionary&lt;/h4&gt;
&lt;p&gt;If the function definition contained a &lt;code&gt;**kwargs&lt;/code&gt; style catch-all for keyword arguments, then a new dictionary is created, and the values are copied across. The &lt;code&gt;kwargs&lt;/code&gt; name is then set as a variable, like in 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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;example&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;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&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;s1&quot;&gt;&amp;#39;extra&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# this would resolve to a dictionary key&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The logic for creating a keyword argument dictionary is in the next part of &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L4045&quot;&gt;_PyEval_EvalCodeWithName()&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* Create a dictionary for keyword parameters (**kwargs) */&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_VARKEYWORDS&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;kwdict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyDict_New&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;kwdict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fail&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;total_args&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_VARARGS&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;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;SETLOCAL&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;kwdict&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;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;kwdict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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 &lt;code&gt;kwdict&lt;/code&gt; variable will reference a &lt;code&gt;PyDictObject&lt;/code&gt; if any keyword arguments were found.&lt;/p&gt;
&lt;h4 id=&quot;4-converting-positional-arguments-into-variables&quot;&gt;4. Converting Positional Arguments Into Variables&lt;/h4&gt;
&lt;p&gt;Next, each of the positional arguments (if provided) are set as local variables:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* Copy all positional arguments into local variables */&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;argcount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_argcount&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;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_argcount&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;else&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;n&quot;&gt;argcount&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_INCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;SETLOCAL&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;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At the end of the loop, you&amp;rsquo;ll see a call to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L1005&quot;&gt;&lt;code&gt;SETLOCAL()&lt;/code&gt;&lt;/a&gt; with the value, so if a positional argument is defined with a value, that is available within this scope: &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;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg2&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;arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# both args are already local variables.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also, the reference counter for those variables is incremented, so the garbage collector won&amp;rsquo;t remove them until the frame has evaluated.&lt;/p&gt;
&lt;h4 id=&quot;5-packing-positional-arguments-into-args&quot;&gt;5. Packing Positional Arguments Into &lt;code&gt;*args&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Similar to &lt;code&gt;**kwargs&lt;/code&gt;, a function argument prepended with a &lt;code&gt;*&lt;/code&gt; can be set to catch all remaining positional arguments. This argument is a tuple and the &lt;code&gt;*args&lt;/code&gt; name is set as a local variable: &lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* Pack other positional arguments into the *args argument */&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_VARARGS&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;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyTuple_FromArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argcount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fail&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;SETLOCAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&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;h4 id=&quot;6-loading-keyword-arguments&quot;&gt;6. Loading Keyword Arguments&lt;/h4&gt;
&lt;p&gt;If the function was called with keyword arguments and values, the &lt;code&gt;kwdict&lt;/code&gt; dictionary created in step 4 is now filled with any remaining keyword arguments passed by the caller that doesn&amp;rsquo;t resolve to named arguments or positional arguments.&lt;/p&gt;
&lt;p&gt;For example, the &lt;code&gt;e&lt;/code&gt; argument was neither positional or named, so it is added to &lt;code&gt;**remaining&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;       print(a, b, c, d, remaining)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&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;n&quot;&gt;e&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;go&quot;&gt;(1, 2, 3, 4, {&amp;#39;e&amp;#39;: 5})&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Positional-only arguments&lt;/strong&gt; is a new feature in Python 3.8. Introduced in &lt;a href=&quot;https://www.python.org/dev/peps/pep-0570/&quot;&gt;PEP570&lt;/a&gt;, positional-only arguments are a way of stopping users of your API from using positional arguments with a keyword syntax.&lt;/p&gt;
&lt;p&gt;For example, this simple function converts Farenheit to Celcius. Note, the use of &lt;code&gt;/&lt;/code&gt; as a special argument seperates positional-only arguments from the other arguments.&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;to_celcius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;farenheit&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;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;farenheit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;31&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;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All arguments to the left of &lt;code&gt;/&lt;/code&gt; must be called only as a positional argument, and arguments to the right can be called as either positional or keyword 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;n&quot;&gt;to_celcius&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Calling the function using a keyword argument to a positional-only argument will raise a &lt;code&gt;TypeError&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;to_celcius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;farenheit&lt;/span&gt;&lt;span class=&quot;o&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;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_celcius() got some positional-only arguments passed as keyword arguments: &amp;#39;farenheit&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;The resolution of the keyword argument dictionary values comes after the unpacking of all other arguments. The PEP570 positional-only arguments are shown by starting the keyword-argument loop at &lt;code&gt;co_posonlyargcount&lt;/code&gt;. If the &lt;code&gt;/&lt;/code&gt; symbol was used on the 3rd argument, the value of &lt;code&gt;co_posonlyargcount&lt;/code&gt; would be &lt;code&gt;2&lt;/code&gt;.
&lt;code&gt;PyDict_SetItem()&lt;/code&gt; is called for each remaining argument to add it to the &lt;code&gt;locals&lt;/code&gt; dictionary, so when executing, each of the keyword arguments are scoped local variables:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;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;0&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwcount&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;kwstep&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_varnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keyword&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwnames&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;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;i&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;cm&quot;&gt;/* Speed hack: do raw pointer compares. As names are&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;           normally interned this should almost always hit. */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;co_varnames&lt;/span&gt; &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;PyTupleObject&lt;/span&gt; &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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_varnames&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;ob_item&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;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_posonlyargcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co_varnames&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;k&quot;&gt;if&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;n&quot;&gt;keyword&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;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kw_found&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwdict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_posonlyargcount&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;positional_only_passed_as_keyword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                                     &lt;span class=&quot;n&quot;&gt;kwcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwnames&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;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fail&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;_PyErr_Format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyExc_TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                          &lt;span class=&quot;s&quot;&gt;&amp;quot;%U() got an unexpected keyword argument &amp;#39;%S&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                          &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fail&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyDict_SetItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwdict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fail&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;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;nl&quot;&gt;kw_found&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;Py_INCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;SETLOCAL&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;n&quot;&gt;value&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;At the end of the loop, you&amp;rsquo;ll see a call to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L1005&quot;&gt;&lt;code&gt;SETLOCAL()&lt;/code&gt;&lt;/a&gt; with the value. If a keyword argument is defined with a value, that is available within this scope:&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;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;example_kwarg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;example_kwarg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# example_kwarg is already a local variable.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&quot;7-adding-missing-positional-arguments&quot;&gt;7. Adding Missing Positional Arguments&lt;/h4&gt;
&lt;p&gt;Any positional arguments provided to a function call that are not in the list of positional arguments are added to a &lt;code&gt;*args&lt;/code&gt; tuple if this tuple does not exist, a failure is raised:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* Add missing positional arguments (copy default values from defs) */&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;argcount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_argcount&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;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_argcount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;missing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&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;argcount&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&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;p&quot;&gt;)&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;GETLOCAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;missing&lt;/span&gt;&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;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;missing&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;missing_arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;missing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fastlocals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fail&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;if&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;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&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;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&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;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defcount&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;p&quot;&gt;)&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;GETLOCAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&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;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defs&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;Py_INCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;SETLOCAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&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;def&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;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&quot;8-adding-missing-keyword-arguments&quot;&gt;8. Adding Missing Keyword Arguments&lt;/h4&gt;
&lt;p&gt;Any keyword arguments provided to a function call that are not in the list of named keyword arguments are added to a &lt;code&gt;**kwargs&lt;/code&gt; dictionary if this dictionary does not exist, a failure is raised:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* Add missing keyword arguments (copy default values from kwdefs) */&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_kwonlyargcount&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;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;missing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_argcount&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total_args&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;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GETLOCAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;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;n&quot;&gt;PyTuple_GET_ITEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_varnames&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwdefs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyDict_GetItemWithError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwdefs&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;p&quot;&gt;...&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;missing&lt;/span&gt;&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;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&quot;9-collapsing-closures&quot;&gt;9. Collapsing Closures&lt;/h4&gt;
&lt;p&gt;Any closure names are added to the code object&amp;rsquo;s list of free variable names:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* Copy closure variables to free variables */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&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;0&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyTuple_GET_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_freevars&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;i&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyTuple_GET_ITEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;closure&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;Py_INCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;freevars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyTuple_GET_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_cellvars&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;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&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;h4 id=&quot;10-creating-generators-coroutines-and-asynchronous-generators&quot;&gt;10. Creating Generators, Coroutines, and Asynchronous Generators&lt;/h4&gt;
&lt;p&gt;If the evaluated code object has a flag that it is a generator, coroutine or async generator, then a new frame is created using one of the unique methods in the Generator, Coroutine or Async libraries and the current frame is added as a property.&lt;/p&gt;
&lt;p&gt;The new frame is then returned, and the original frame is not evaluated. The frame is only evaluated when the generator/coroutine/async method is called on to execute its target:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* Handle generator/coroutine/asynchronous generator */&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CO_GENERATOR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_COROUTINE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_ASYNC_GENERATOR&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;cm&quot;&gt;/* Create a new generator that owns the ready to run frame&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;         * and return that as the value. */&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;is_coro&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;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCoro_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualname&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;else&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_ASYNC_GENERATOR&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;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyAsyncGen_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualname&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;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyGen_NewWithQualName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualname&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gen&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;Lastly, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L738&quot;&gt;&lt;code&gt;PyEval_EvalFrameEx()&lt;/code&gt;&lt;/a&gt; is called with the new frame:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyEval_EvalFrameEx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;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;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&quot;frame-execution&quot;&gt;Frame Execution&lt;/h4&gt;
&lt;p&gt;As covered earlier in the compiler and AST chapters, the code object contains a binary encoding of the bytecode to be executed. It also contains a list of variables and a symbol table.&lt;/p&gt;
&lt;p&gt;The local and global variables are determined at runtime based on how that function, module, or block was called. This information is added to the frame by the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L4045&quot;&gt;&lt;code&gt;_PyEval_EvalCodeWithName()&lt;/code&gt;&lt;/a&gt; function. There are other usages of frames, like the coroutine decorator, which dynamically generates a frame with the target as a variable.&lt;/p&gt;
&lt;p&gt;The public API, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L738&quot;&gt;&lt;code&gt;PyEval_EvalFrameEx()&lt;/code&gt;&lt;/a&gt; calls the interpreter&amp;rsquo;s configured frame evaluation function in the &lt;code&gt;eval_frame&lt;/code&gt; property. Frame evaluation was &lt;a href=&quot;https://www.python.org/dev/peps/pep-0523/&quot;&gt;made pluggable in Python 3.7 with PEP 523&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L745&quot;&gt;&lt;code&gt;_PyEval_EvalFrameDefault()&lt;/code&gt;&lt;/a&gt; is the default function, and it is unusual to use anything other than this. &lt;/p&gt;
&lt;p&gt;Frames are executed in the main execution loop inside &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L745&quot;&gt;&lt;code&gt;_PyEval_EvalFrameDefault()&lt;/code&gt;&lt;/a&gt;. This function is central function that brings everything together and brings your code to life. It contains decades of optimization since even a single line of code can have a significant impact on performance for the whole of CPython.&lt;/p&gt;
&lt;p&gt;Everything that gets executed in CPython goes through this function.&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; Something you might notice when reading &lt;code&gt;ceval.c&lt;/code&gt;, is how many times C macros have been used. C Macros are a way of having DRY-compliant code without the overhead of making function calls. The compiler converts the macros into C code and then compile the generated code. &lt;/p&gt;
&lt;p&gt;If you want to see the expanded code, you can run &lt;code&gt;gcc -E&lt;/code&gt; on Linux and macOS:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; gcc -E Python/ceval.c
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, &lt;a href=&quot;https://realpython.com/python-development-visual-studio-code/&quot;&gt;Visual Studio Code&lt;/a&gt; can do inline macro expansion once you have installed the official C/C++ extension:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-25_at_3.33.40_pm.c240b1a46e99.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/Screen_Shot_2019-03-25_at_3.33.40_pm.c240b1a46e99.png&quot; width=&quot;1866&quot; height=&quot;622&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-25_at_3.33.40_pm.c240b1a46e99.png&amp;amp;w=466&amp;amp;sig=28bc3a2f62e499a92fdac8fbd951c6ab5a18d361 466w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-25_at_3.33.40_pm.c240b1a46e99.png&amp;amp;w=933&amp;amp;sig=ec297187398d1a9b390bdadedd2c96855b2dfacc 933w, https://files.realpython.com/media/Screen_Shot_2019-03-25_at_3.33.40_pm.c240b1a46e99.png 1866w&quot; sizes=&quot;75vw&quot; alt=&quot;C Macro expansion with VScode&quot;/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can step through frame execution in Python 3.7 and beyond by enabling the tracing attribute on the current thread.&lt;/p&gt;
&lt;p&gt;This code example sets the global tracing function to a function called &lt;code&gt;trace()&lt;/code&gt; that gets the stack from the current frame, prints the disassembled opcodes to the screen, and some extra information for debugging:&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;sys&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dis&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;traceback&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;trace&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;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;args&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;f_trace_opcodes&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;stack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;traceback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extract_stack&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;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;pad&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&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;|&amp;quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;if&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;s1&quot;&gt;&amp;#39;opcode&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StringIO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;dis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disco&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;f_code&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;f_lasti&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{pad}{l}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;elif&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;s1&quot;&gt;&amp;#39;call&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{pad}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Calling &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{frame.f_code}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;elif&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;s1&quot;&gt;&amp;#39;return&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{pad}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Returning &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{args}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;elif&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;s1&quot;&gt;&amp;#39;line&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{pad}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Changing line to &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{frame.f_lineno}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{pad}{frame}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{event}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; - &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{args}&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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{pad}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;----------------------------------&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trace&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;settrace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Run some code for a demo&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;s1&quot;&gt;&amp;#39;&amp;quot;-&amp;quot;.join([letter for letter in &amp;quot;hello&amp;quot;])&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This prints the code within each stack and point to the next operation before it is executed. When a frame returns a value, the return statement is printed:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Screen_Shot_2019-03-25_at_1.21.07_pm.7b03e9032f62.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/Screen_Shot_2019-03-25_at_1.21.07_pm.7b03e9032f62.png&quot; width=&quot;2572&quot; height=&quot;1686&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-25_at_1.21.07_pm.7b03e9032f62.png&amp;amp;w=643&amp;amp;sig=6d6106abaf9fb5f3d7e45e09320c7575b3a0e77c 643w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Screen_Shot_2019-03-25_at_1.21.07_pm.7b03e9032f62.png&amp;amp;w=1286&amp;amp;sig=c41bf26bd15641fded6a31125b0cb5b630496647 1286w, https://files.realpython.com/media/Screen_Shot_2019-03-25_at_1.21.07_pm.7b03e9032f62.png 2572w&quot; sizes=&quot;75vw&quot; alt=&quot;Evaluating frame with tracing&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The full list of instructions is available on the &lt;a href=&quot;https://docs.python.org/3/library/dis.html#python-bytecode-instructions&quot;&gt;&lt;code&gt;dis&lt;/code&gt; module&lt;/a&gt; documentation. &lt;/p&gt;
&lt;h4 id=&quot;the-value-stack&quot;&gt;The Value Stack&lt;/h4&gt;
&lt;p&gt;Inside the core evaluation loop, a value stack is created. This stack is a list of pointers to sequential &lt;code&gt;PyObject&lt;/code&gt; instances.&lt;/p&gt;
&lt;p&gt;One way to think of the value stack is like a wooden peg on which you can stack cylinders. You would only add or remove one item at a time. This is done using the &lt;code&gt;PUSH(a)&lt;/code&gt; macro, where &lt;code&gt;a&lt;/code&gt; is a pointer to a &lt;code&gt;PyObject&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, if you created a &lt;code&gt;PyLong&lt;/code&gt; with the value 10 and pushed it onto the value stack:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_FromLong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;PUSH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This action would have the following effect:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stacks_push.0c755d83b347.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid &quot; src=&quot;https://files.realpython.com/media/stacks_push.0c755d83b347.png&quot; width=&quot;822&quot; height=&quot;279&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_push.0c755d83b347.png&amp;amp;w=205&amp;amp;sig=d3ce00e768e8c7f89ef321ea039b159131b39d8a 205w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_push.0c755d83b347.png&amp;amp;w=411&amp;amp;sig=65cf700de41fd59781082f03c5d347fd891ac5a9 411w, https://files.realpython.com/media/stacks_push.0c755d83b347.png 822w&quot; sizes=&quot;75vw&quot; alt=&quot;PUSH()&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the next operation, to fetch that value, you would use the &lt;code&gt;POP()&lt;/code&gt; macro to take the top value from the stack:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;POP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// a is PyLongObject with a value of 10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This action would return the top value and end up with an empty value stack:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stacks_pop.85872baaa8c3.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid &quot; src=&quot;https://files.realpython.com/media/stacks_pop.85872baaa8c3.png&quot; width=&quot;778&quot; height=&quot;226&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_pop.85872baaa8c3.png&amp;amp;w=194&amp;amp;sig=887719d9b65d3ef671e2310aae15904e04acba28 194w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_pop.85872baaa8c3.png&amp;amp;w=389&amp;amp;sig=6950fcd6370022df61559d12b74c6b685a61e238 389w, https://files.realpython.com/media/stacks_pop.85872baaa8c3.png 778w&quot; sizes=&quot;75vw&quot; alt=&quot;POP()&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you were to add 2 values to the stack:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_FromLong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&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;PyLong_FromLong&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;n&quot;&gt;PUSH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;PUSH&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;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;They would end up in the order in which they were added, so &lt;code&gt;a&lt;/code&gt; would be pushed to the second position in the stack:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stacks_pushpush.e052996db029.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid &quot; src=&quot;https://files.realpython.com/media/stacks_pushpush.e052996db029.png&quot; width=&quot;783&quot; height=&quot;226&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_pushpush.e052996db029.png&amp;amp;w=195&amp;amp;sig=47cc1b6b30f314f1589eb9c8188efcd3eb0ef79e 195w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_pushpush.e052996db029.png&amp;amp;w=391&amp;amp;sig=a0813bcc81d314c3f2f0eb146634ba187d447634 391w, https://files.realpython.com/media/stacks_pushpush.e052996db029.png 783w&quot; sizes=&quot;75vw&quot; alt=&quot;PUSH();PUSH()&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you were to fetch the top value in the stack, you would get a pointer to &lt;code&gt;b&lt;/code&gt; because it is at the top:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stacks_pop2.af5068718f92.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid &quot; src=&quot;https://files.realpython.com/media/stacks_pop2.af5068718f92.png&quot; width=&quot;789&quot; height=&quot;226&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_pop2.af5068718f92.png&amp;amp;w=197&amp;amp;sig=1856b32d5f95f58eb2ad60a549165f85bf2b4d7a 197w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_pop2.af5068718f92.png&amp;amp;w=394&amp;amp;sig=ce3ba993ee2fa8cb037bb84144c73f95450954ac 394w, https://files.realpython.com/media/stacks_pop2.af5068718f92.png 789w&quot; sizes=&quot;75vw&quot; alt=&quot;POP();&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you need to fetch the pointer to the top value in the stack without popping it, you can use the &lt;code&gt;PEEK(v)&lt;/code&gt; operation, where &lt;code&gt;v&lt;/code&gt; is the stack position:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PEEK&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;0 represents the top of the stack, 1 would be the second position:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stacks_peek.b00bde86bc7b.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid &quot; src=&quot;https://files.realpython.com/media/stacks_peek.b00bde86bc7b.png&quot; width=&quot;802&quot; height=&quot;174&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_peek.b00bde86bc7b.png&amp;amp;w=200&amp;amp;sig=fac4fef886154a979f9abe7316e9468179c14c71 200w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_peek.b00bde86bc7b.png&amp;amp;w=401&amp;amp;sig=463aeb044f65a4c446a37c71cd86ae71564a2ec6 401w, https://files.realpython.com/media/stacks_peek.b00bde86bc7b.png 802w&quot; sizes=&quot;75vw&quot; alt=&quot;PEEK()&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To clone the value at the top of the stack, the &lt;code&gt;DUP_TWO()&lt;/code&gt; macro can be used, or by using the &lt;code&gt;DUP_TWO&lt;/code&gt; opcode:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DUP_TOP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This action would copy the value at the top to form 2 pointers to the same object:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stacks_duptop.9b2eafe67375.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid &quot; src=&quot;https://files.realpython.com/media/stacks_duptop.9b2eafe67375.png&quot; width=&quot;799&quot; height=&quot;177&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_duptop.9b2eafe67375.png&amp;amp;w=199&amp;amp;sig=3d40e1422f0aa5f3b50b8b174d02f0fe5df54364 199w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_duptop.9b2eafe67375.png&amp;amp;w=399&amp;amp;sig=11e2d5a69b3dd385c9201d7ab4eeb902f8fa20c9 399w, https://files.realpython.com/media/stacks_duptop.9b2eafe67375.png 799w&quot; sizes=&quot;75vw&quot; alt=&quot;DUP_TOP()&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is a rotation macro &lt;code&gt;ROT_TWO&lt;/code&gt; that swaps the first and second values:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stacks_rottwo.2990d9b3ecc7.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid &quot; src=&quot;https://files.realpython.com/media/stacks_rottwo.2990d9b3ecc7.png&quot; width=&quot;803&quot; height=&quot;175&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_rottwo.2990d9b3ecc7.png&amp;amp;w=200&amp;amp;sig=e3e88549e9801f463358ad1e8b5635ba56b77049 200w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stacks_rottwo.2990d9b3ecc7.png&amp;amp;w=401&amp;amp;sig=d2c11f545336f13fa57bc1588f57b7e7f8dc049f 401w, https://files.realpython.com/media/stacks_rottwo.2990d9b3ecc7.png 803w&quot; sizes=&quot;75vw&quot; alt=&quot;ROT_TWO()&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Each of the opcodes have a predefined &amp;ldquo;stack effect,&amp;rdquo; calculated by the &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/compile.c#L878&quot;&gt;&lt;code&gt;stack_effect()&lt;/code&gt;&lt;/a&gt; function inside &lt;code&gt;Python/compile.c&lt;/code&gt;. This function returns the delta in the number of values inside the stack for each opcode.&lt;/p&gt;
&lt;h4 id=&quot;example-adding-an-item-to-a-list&quot;&gt;Example: Adding an Item to a List&lt;/h4&gt;
&lt;p&gt;In Python, when you create a list, the &lt;code&gt;.append()&lt;/code&gt; method is available on the list 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;n&quot;&gt;my_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Where &lt;code&gt;obj&lt;/code&gt; is an object, you want to append to the end of the list.&lt;/p&gt;
&lt;p&gt;There are 2 operations involved in this operation. &lt;code&gt;LOAD_FAST&lt;/code&gt;, to load the object &lt;code&gt;obj&lt;/code&gt; to the top of the value stack from the list of &lt;code&gt;locals&lt;/code&gt; in the frame, and &lt;code&gt;LIST_APPEND&lt;/code&gt; to add the object.&lt;/p&gt;
&lt;p&gt;First exploring &lt;code&gt;LOAD_FAST&lt;/code&gt;, there are 5 steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The pointer to &lt;code&gt;obj&lt;/code&gt; is loaded from &lt;code&gt;GETLOCAL()&lt;/code&gt;, where the variable to load is the operation argument. The list of variable pointers is stored in &lt;code&gt;fastlocals&lt;/code&gt;, which is a copy of the PyFrame attribute &lt;code&gt;f_localsplus&lt;/code&gt;. The operation argument is a number, pointing to the index in the &lt;code&gt;fastlocals&lt;/code&gt; array pointer. This means that the loading of a local is simply a copy of the pointer instead of having to look up the variable name.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If variable no longer exists, an unbound local variable error is raised.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The reference counter for &lt;code&gt;value&lt;/code&gt; (in our case, &lt;code&gt;obj&lt;/code&gt;) is increased by 1.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The pointer to &lt;code&gt;obj&lt;/code&gt; is pushed to the top of the value stack.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;FAST_DISPATCH&lt;/code&gt; macro is called, if tracing is enabled, the loop goes over again (with all the tracing), if tracing is not enabled, a &lt;code&gt;goto&lt;/code&gt; is called to &lt;code&gt;fast_next_opcode&lt;/code&gt;, which jumps back to the top of the loop for the next instruction.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TARGET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LOAD_FAST&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GETLOCAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;oparg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;// 1.&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;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;format_exc_check_arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;PyExc_UnboundLocalError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;UNBOUNDLOCAL_ERROR_MSG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;PyTuple_GetItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_varnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oparg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                    &lt;span class=&quot;c1&quot;&gt;// 2.&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_INCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                                  &lt;span class=&quot;c1&quot;&gt;// 3.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;PUSH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                                       &lt;span class=&quot;c1&quot;&gt;// 4.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;FAST_DISPATCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;                                   &lt;span class=&quot;c1&quot;&gt;// 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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the pointer to &lt;code&gt;obj&lt;/code&gt; is at the top of the value stack. The next instruction &lt;code&gt;LIST_APPEND&lt;/code&gt; is run.&lt;/p&gt;
&lt;p&gt;Many of the bytecode operations are referencing the base types, like PyUnicode, PyNumber. For example, &lt;code&gt;LIST_APPEND&lt;/code&gt; appends an object to the end of a list. To achieve this, it pops the pointer from the value stack and returns the pointer to the last object in the stack. The macro is a shortcut for: &lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack_pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the pointer to &lt;code&gt;obj&lt;/code&gt; is stored as &lt;code&gt;v&lt;/code&gt;. The list pointer is loaded from &lt;code&gt;PEEK(oparg)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then the C API for Python lists is called for &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;v&lt;/code&gt;. The code for this is inside &lt;code&gt;Objects/listobject.c&lt;/code&gt;, which we go into in the next chapter.&lt;/p&gt;
&lt;p&gt;A call to &lt;code&gt;PREDICT&lt;/code&gt; is made, which guesses that the next operation will be &lt;code&gt;JUMP_ABSOLUTE&lt;/code&gt;. The &lt;code&gt;PREDICT&lt;/code&gt; macro has compiler-generated &lt;code&gt;goto&lt;/code&gt; statements for each of the potential operations&amp;rsquo; &lt;code&gt;case&lt;/code&gt; statements. This means the CPU can jump to that instruction and not have to go through the loop again:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TARGET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LIST_APPEND&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;POP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PEEK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;oparg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&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;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyList_Append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PREDICT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JUMP_ABSOLUTE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;DISPATCH&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;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Opcode predictions:&lt;/strong&gt; 
Some opcodes tend to come in pairs thus making it possible to predict the second code when the first is run.  For example, &lt;code&gt;COMPARE_OP&lt;/code&gt; is often followed by &lt;code&gt;POP_JUMP_IF_FALSE&lt;/code&gt; or &lt;code&gt;POP_JUMP_IF_TRUE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Verifying the prediction costs a single high-speed test of a register variable against a constant.  If the pairing was good, then the processor&amp;rsquo;s own internal branch predication has a high likelihood of success, resulting in a nearly zero-overhead transition to the next opcode.  A successful prediction saves a trip through the eval-loop including its unpredictable switch-case branch.  Combined with the processor&amp;rsquo;s internal branch prediction, a successful PREDICT has the effect of making the two opcodes run as if they were a single new opcode with the bodies combined.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;If collecting opcode statistics, you have two choices:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Keep the predictions turned-on and interpret the results as if some opcodes had been combined&lt;/li&gt;
&lt;li&gt;Turn off predictions so that the opcode frequency counter updates for both opcodes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Opcode prediction is disabled with threaded code since the latter allows the CPU to record separate branch prediction information for each opcode.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Some of the operations, such as &lt;code&gt;CALL_FUNCTION&lt;/code&gt;, &lt;code&gt;CALL_METHOD&lt;/code&gt;, have an operation argument referencing another compiled function. In these cases, another frame is pushed to the frame stack in the thread, and the evaluation loop is run for that function until the function completes. Each time a new frame is created and pushed onto the stack, the value of the frame&amp;rsquo;s &lt;code&gt;f_back&lt;/code&gt; is set to the current frame before the new one is created.&lt;/p&gt;
&lt;p&gt;This nesting of frames is clear when you see a stack trace, take this example script:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function2&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;RuntimeError&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;function2&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;function1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Calling this on the command line will give you:&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.exe example_stack.py

&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;example_stack.py&amp;quot;, line 8, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    function1()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;example_stack.py&amp;quot;, line 5, in function1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    function2()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;example_stack.py&amp;quot;, line 2, in function2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    raise RuntimeError&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;RuntimeError&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;traceback.py&lt;/code&gt;, the &lt;code&gt;walk_stack()&lt;/code&gt; function used to print trace backs:&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;walk_stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Walk a stack yielding the frame and line number for each frame.&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;    This will follow f.f_back from the given frame. If no frame is given, the&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    current stack is used. Usually used with StackSummary.extract.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &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;f&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;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_getframe&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;f_back&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_back&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_lineno&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_back&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here you can see that the current frame, fetched by calling &lt;code&gt;sys._getframe()&lt;/code&gt; and the parent&amp;rsquo;s parent is set as the frame, because you don&amp;rsquo;t want to see the call to &lt;code&gt;walk_stack()&lt;/code&gt; or &lt;code&gt;print_trace()&lt;/code&gt; in the trace back, so those function frames are skipped.&lt;/p&gt;
&lt;p&gt;Then the &lt;code&gt;f_back&lt;/code&gt; pointer is followed to the top.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sys._getframe()&lt;/code&gt; is the Python API to get the &lt;code&gt;frame&lt;/code&gt; attribute of the current thread.&lt;/p&gt;
&lt;p&gt;Here is how that frame stack would look visually, with 3 frames each with its code object and a thread state pointing to the current frame:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Frame_Stack_Example.20728854763c.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/Frame_Stack_Example.20728854763c.png&quot; width=&quot;841&quot; height=&quot;1556&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Frame_Stack_Example.20728854763c.png&amp;amp;w=210&amp;amp;sig=bb2e7a72a4363554566003b8412f81c843a8edc2 210w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Frame_Stack_Example.20728854763c.png&amp;amp;w=420&amp;amp;sig=17eddfb3f22ccab1056545af3055470669c4ce3f 420w, https://files.realpython.com/media/Frame_Stack_Example.20728854763c.png 841w&quot; sizes=&quot;75vw&quot; alt=&quot;Example frame stack&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;conclusion_3&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this Part, you explored the most complex element of CPython: the compiler. The original author of Python, Guido van Rossum, made the statement that CPython&amp;rsquo;s compiler should be &amp;ldquo;dumb&amp;rdquo; so that people can understand it.&lt;/p&gt;
&lt;p&gt;By breaking down the compilation process into small, logical steps, it is far easier to understand.&lt;/p&gt;
&lt;p&gt;In the next chapter, we connect the compilation process with the basis of all Python code, the &lt;code&gt;object&lt;/code&gt;.&lt;/p&gt;
&lt;h2 h1=&quot;h1&quot; id=&quot;part-4-objects-in-cpython&quot;&gt;Part 4: Objects in CPython&lt;/h2&gt;
&lt;p&gt;CPython comes with a collection of basic types like strings, lists, tuples, dictionaries, and objects.&lt;/p&gt;
&lt;p&gt;All of these types are built-in. You don&amp;rsquo;t need to import any libraries, even from the standard library. Also, the instantiation of these built-in types has some handy shortcuts.&lt;/p&gt;
&lt;p&gt;For example, to create a new list, you can 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;n&quot;&gt;lst&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or, you can use square brackets:&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;lst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Strings can be instantiated from a string-literal by using either double or single quotes. We explored the grammar definitions earlier that cause the compiler to interpret double quotes as a string literal. &lt;/p&gt;
&lt;p&gt;All types in Python inherit from &lt;code&gt;object&lt;/code&gt;, a built-in base type. Even strings, tuples, and list inherit from &lt;code&gt;object&lt;/code&gt;. During the walk-through of the C code, you have read lots of references to &lt;code&gt;PyObject*&lt;/code&gt;, the C-API structure for an &lt;code&gt;object&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because C is not object-oriented &lt;a href=&quot;https://realpython.com/python3-object-oriented-programming/&quot;&gt;like Python&lt;/a&gt;, objects in C don&amp;rsquo;t inherit from one another. &lt;code&gt;PyObject&lt;/code&gt; is the data structure for the beginning of the Python object&amp;rsquo;s memory.&lt;/p&gt;
&lt;p&gt;Much of the base object API is declared in &lt;code&gt;Objects/object.c&lt;/code&gt;, like the function &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L505&quot;&gt;&lt;code&gt;PyObject_Repr&lt;/code&gt;&lt;/a&gt;, which the built-in &lt;code&gt;repr()&lt;/code&gt; function. You will also find &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L810&quot;&gt;&lt;code&gt;PyObject_Hash()&lt;/code&gt;&lt;/a&gt; and other APIs.&lt;/p&gt;
&lt;p&gt;All of these functions can be overridden in a custom object by implementing &amp;ldquo;dunder&amp;rdquo; methods on a Python 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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;id&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;bp&quot;&gt;self&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;nb&quot;&gt;id&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;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__repr__&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;s2&quot;&gt;&amp;quot;&amp;lt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{0}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; id=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{1}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code is implemented in &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/object.c#L505&quot;&gt;&lt;code&gt;PyObject_Repr()&lt;/code&gt;&lt;/a&gt;, inside &lt;code&gt;Objects/object.c&lt;/code&gt;. The type of the target object, &lt;code&gt;v&lt;/code&gt; will be inferred through a call to &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/object.h#L122&quot;&gt;&lt;code&gt;Py_TYPE()&lt;/code&gt;&lt;/a&gt; and if the &lt;code&gt;tp_repr&lt;/code&gt; field is set, then the function pointer is called.
If the &lt;code&gt;tp_repr&lt;/code&gt; field is not set, i.e. the object doesn&amp;rsquo;t declare a custom &lt;code&gt;__repr__&lt;/code&gt; method, then the default behavior is run, which is to return &lt;code&gt;&quot;&amp;lt;%s object at %p&amp;gt;&quot;&lt;/code&gt; with the type name and the ID:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyObject_Repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&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;PyErr_CheckSignals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;PyUnicode_FromString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;lt;NULL&amp;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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Py_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp_repr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyUnicode_FromFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;lt;%s object at %p&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ob_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;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 ob_type field for a given &lt;code&gt;PyObject*&lt;/code&gt; will point to the data structure &lt;code&gt;PyTypeObject&lt;/code&gt;, defined in &lt;code&gt;Include/cpython/object.h&lt;/code&gt;.
This data-structure lists all the built-in functions, as fields and the arguments they should receive.&lt;/p&gt;
&lt;p&gt;Take &lt;code&gt;tp_repr&lt;/code&gt; as an example:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_typeobject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject_VAR_HEAD&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* For printing, in format &amp;quot;&amp;lt;module&amp;gt;.&amp;lt;name&amp;gt;&amp;quot; */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tp_basicsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tp_itemsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* For allocation */&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* Methods to implement standard operations */&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;reprfunc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tp_repr&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;Where &lt;code&gt;reprfunc&lt;/code&gt; is a &lt;code&gt;typedef&lt;/code&gt; for &lt;code&gt;PyObject *(*reprfunc)(PyObject *);&lt;/code&gt;, a function that takes 1 pointer to &lt;code&gt;PyObject&lt;/code&gt; (&lt;code&gt;self&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Some of the dunder APIs are optional, because they only apply to certain types, like numbers:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* Method suites for standard classes */&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;PyNumberMethods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp_as_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PySequenceMethods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp_as_sequence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyMappingMethods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp_as_mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A sequence, like a list would implement the following methods:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;lenfunc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sq_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// len(v)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;binaryfunc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sq_concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// v + x&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ssizeargfunc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sq_repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// for x in v&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ssizeargfunc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sq_item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// v[x]&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;was_sq_slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// v[x:y:z]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ssizeobjargproc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sq_ass_item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// v[x] = z&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;was_sq_ass_slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// v[x:y] = z&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;objobjproc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sq_contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// x in v&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;binaryfunc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sq_inplace_concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ssizeargfunc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sq_inplace_repeat&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;PySequenceMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All of these built-in functions are called the &lt;a href=&quot;https://docs.python.org/3/reference/datamodel.html&quot;&gt;Python Data Model&lt;/a&gt;. One of the great resources for the Python Data Model is &lt;a href=&quot;https://www.oreilly.com/library/view/fluent-python/9781491946237/&quot;&gt;&amp;ldquo;Fluent Python&amp;rdquo; by Luciano Ramalho&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;base-object-type&quot;&gt;Base Object Type&lt;/h3&gt;
&lt;p&gt;In &lt;code&gt;Objects/object.c&lt;/code&gt;, the base implementation of &lt;code&gt;object&lt;/code&gt; type is written as pure C code. There are some concrete implementations of basic logic, like shallow comparisons.&lt;/p&gt;
&lt;p&gt;Not all methods in a Python object are part of the Data Model, so that a Python object can contain attributes (either class or instance attributes) and methods.&lt;/p&gt;
&lt;p&gt;A simple way to think of a Python object is consisting of 2 things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The core data model, with pointers to compiled functions&lt;/li&gt;
&lt;li&gt;A dictionary with any custom attributes and methods&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The core data model is defined in the &lt;code&gt;PyTypeObject&lt;/code&gt;, and the functions are defined in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Objects/object.c&lt;/code&gt; for the built-in methods&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/boolobject.c&lt;/code&gt; for the &lt;code&gt;bool&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/bytearrayobject.c&lt;/code&gt; for the &lt;code&gt;byte[]&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/bytesobjects.c&lt;/code&gt; for the &lt;code&gt;bytes&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/cellobject.c&lt;/code&gt; for the &lt;code&gt;cell&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/classobject.c&lt;/code&gt; for the abstract &lt;code&gt;class&lt;/code&gt; type, used in meta-programming&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/codeobject.c&lt;/code&gt; used for the built-in &lt;code&gt;code&lt;/code&gt; object type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/complexobject.c&lt;/code&gt; for a complex numeric type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/iterobject.c&lt;/code&gt; for an iterator&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/listobject.c&lt;/code&gt; for the &lt;code&gt;list&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/longobject.c&lt;/code&gt; for the &lt;code&gt;long&lt;/code&gt; numeric type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/memoryobject.c&lt;/code&gt; for the base memory type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/methodobject.c&lt;/code&gt; for the class method type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/moduleobject.c&lt;/code&gt; for a module type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/namespaceobject.c&lt;/code&gt; for a namespace type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/odictobject.c&lt;/code&gt; for an ordered dictionary type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/rangeobject.c&lt;/code&gt; for a range generator&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/setobject.c&lt;/code&gt; for a &lt;code&gt;set&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/sliceobject.c&lt;/code&gt; for a slice reference type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/structseq.c&lt;/code&gt; for a &lt;a href=&quot;https://docs.python.org/3/library/struct.html#struct.Struct&quot;&gt;&lt;code&gt;struct.Struct&lt;/code&gt;&lt;/a&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/tupleobject.c&lt;/code&gt; for a &lt;code&gt;tuple&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/typeobject.c&lt;/code&gt; for a &lt;code&gt;type&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/unicodeobject.c&lt;/code&gt; for a &lt;code&gt;str&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects/weakrefobject.c&lt;/code&gt; for a &lt;a href=&quot;https://docs.python.org/3/library/weakref.html&quot;&gt;&lt;code&gt;weakref&lt;/code&gt; object&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&amp;rsquo;re going to dive into 3 of these types: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Booleans &lt;/li&gt;
&lt;li&gt;Integers&lt;/li&gt;
&lt;li&gt;Generators&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Booleans and Integers have a lot in common, so we&amp;rsquo;ll cover those first.&lt;/p&gt;
&lt;h3 id=&quot;the-bool-and-long-integer-type&quot;&gt;The Bool and Long Integer Type&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;bool&lt;/code&gt; type is the most straightforward implementation of the built-in types. It inherits from &lt;code&gt;long&lt;/code&gt; and has the predefined constants, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/boolobject.h#L22&quot;&gt;&lt;code&gt;Py_True&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Include/boolobject.h#L21&quot;&gt;&lt;code&gt;Py_False&lt;/code&gt;&lt;/a&gt;. These constants are immutable instances, created on the instantiation of the Python interpreter.&lt;/p&gt;
&lt;p&gt;Inside &lt;code&gt;Objects/boolobject.c&lt;/code&gt;, you can see the helper function to create a &lt;code&gt;bool&lt;/code&gt; instance from a number:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PyBool_FromLong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&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 class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&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;if&lt;/span&gt; &lt;span class=&quot;p&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 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;Py_True&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;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_INCREF&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;return&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;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This function uses the C evaluation of a numeric type to assign &lt;code&gt;Py_True&lt;/code&gt; or &lt;code&gt;Py_False&lt;/code&gt; to a result and increment the reference counters.&lt;/p&gt;
&lt;p&gt;The numeric functions for &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;xor&lt;/code&gt;, and &lt;code&gt;or&lt;/code&gt; are implemented, but addition, subtraction, and division are dereferenced from the base long type since it would make no sense to divide two boolean values.&lt;/p&gt;
&lt;p&gt;The implementation of &lt;code&gt;and&lt;/code&gt; for a &lt;code&gt;bool&lt;/code&gt; value checks if &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are booleans, then check their references to &lt;code&gt;Py_True&lt;/code&gt;, otherwise, are cast as numbers, and the &lt;code&gt;and&lt;/code&gt; operation is run on the two numbers:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;bool_and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&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;if&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;PyBool_Check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyBool_Check&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;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp_as_number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nb_and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyBool_FromLong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;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;Py_True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;long&lt;/code&gt; type is a bit more complex, as the memory requirements are expansive. In the transition from Python 2 to 3, CPython dropped support for the &lt;code&gt;int&lt;/code&gt; type and instead used the &lt;code&gt;long&lt;/code&gt; type as the primary integer type. Python&amp;rsquo;s &lt;code&gt;long&lt;/code&gt; type is quite special in that it can store a variable-length number. The maximum length is set in the compiled binary.&lt;/p&gt;
&lt;p&gt;The data structure of a Python &lt;code&gt;long&lt;/code&gt; consists of the &lt;code&gt;PyObject&lt;/code&gt; header and a list of digits. The list of digits, &lt;code&gt;ob_digit&lt;/code&gt; is initially set to have one digit, but it later expanded to a longer length when initialized:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_longobject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PyObject_VAR_HEAD&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;digit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ob_digit&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;p&quot;&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Memory is allocated to a new &lt;code&gt;long&lt;/code&gt; through &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/longobject.c#L262&quot;&gt;&lt;code&gt;_PyLong_New()&lt;/code&gt;&lt;/a&gt;. This function takes a fixed length and makes sure it is smaller than &lt;code&gt;MAX_LONG_DIGITS&lt;/code&gt;. Then it reallocates the memory for &lt;code&gt;ob_digit&lt;/code&gt; to match the length.&lt;/p&gt;
&lt;p&gt;To convert a C &lt;code&gt;long&lt;/code&gt; type to a Python &lt;code&gt;long&lt;/code&gt; type, the &lt;code&gt;long&lt;/code&gt; is converted to a list of digits, the memory for the Python &lt;code&gt;long&lt;/code&gt; is assigned, and then each of the digits is set.
Because &lt;code&gt;long&lt;/code&gt; is initialized with &lt;code&gt;ob_digit&lt;/code&gt; already being at a length of 1, if the number is less than 10, then the value is set without the memory being allocated:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyLong_FromLong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ival&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;PyLongObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abs_ival&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/* unsigned so &amp;gt;&amp;gt; doesn&amp;#39;t propagate sign bit */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ndigits&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;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;CHECK_SMALL_INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ival&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;cm&quot;&gt;/* Fast path for single-digit ints */&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs_ival&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_SHIFT&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;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyLong_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Py_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ob_digit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_SAFE_DOWNCAST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;abs_ival&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt;&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;v&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;cm&quot;&gt;/* Larger numbers: loop to determine number of digits */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abs_ival&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;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndigits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_SHIFT&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;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyLong_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndigits&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;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;digit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ob_digit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ndigits&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abs_ival&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;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_SAFE_DOWNCAST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_MASK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_SHIFT&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;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &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;v&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;To convert a &lt;a href=&quot;https://en.wikipedia.org/wiki/Double-precision_floating-point_format&quot;&gt;double-point floating point&lt;/a&gt; to a Python &lt;code&gt;long&lt;/code&gt;, &lt;code&gt;PyLong_FromDouble()&lt;/code&gt; does the math for you:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;PyLong_FromDouble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dval&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;PyLongObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ndig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;neg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;neg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Py_IS_INFINITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dval&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;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_OverflowError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&amp;quot;cannot convert float infinity to integer&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Py_IS_NAN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dval&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;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&amp;quot;cannot convert float NaN to integer&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.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;n&quot;&gt;neg&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;dval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dval&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;frac&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* dval = frac*2**expo; 0.0 &amp;lt;= frac &amp;lt; 1.0 */&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;expo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_FromLong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0L&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ndig&lt;/span&gt; &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;expo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_SHIFT&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;cm&quot;&gt;/* Number of &amp;#39;digits&amp;#39; in result */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyLong_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndig&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;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;frac&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frac&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;expo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_SHIFT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;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;ndig&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;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;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;digit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bits&lt;/span&gt; &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;digit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ob_digit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;frac&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frac&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;frac&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyLong_SHIFT&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&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;Py_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &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;v&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 remainder of the implementation functions in &lt;code&gt;longobject.c&lt;/code&gt; have utilities, such as converting a Unicode string into a number with &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/longobject.c#L2672&quot;&gt;&lt;code&gt;PyLong_FromUnicodeObject()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;a-review-of-the-generator-type&quot;&gt;A Review of the Generator Type&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://realpython.com/introduction-to-python-generators/&quot;&gt;Python Generators&lt;/a&gt; are functions which return a &lt;code&gt;yield&lt;/code&gt; statement and can be called continually to generate further values.&lt;/p&gt;
&lt;p&gt;Commonly they are used as a more memory efficient way of looping through values in a large block of data, like a file, a database or over a network. &lt;/p&gt;
&lt;p&gt;Generator objects are returned in place of a value when &lt;code&gt;yield&lt;/code&gt; is used instead of &lt;code&gt;return&lt;/code&gt;. The generator object is created from the &lt;code&gt;yield&lt;/code&gt; statement and returned to the caller.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create a simple generator with a list of 4 constant values:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;example&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;lst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;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;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;lst&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;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&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;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;generator object example at 0x100bcc480&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you explore the contents of the generator object, you can see some of the fields starting with &lt;code&gt;gi_&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[ ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;close&amp;#39;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;gi_code&amp;#39;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;gi_frame&amp;#39;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;gi_running&amp;#39;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;gi_yieldfrom&amp;#39;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;send&amp;#39;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;throw&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;PyGenObject&lt;/code&gt; type is defined in &lt;code&gt;Include/genobject.h&lt;/code&gt; and there are 3 flavors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generator objects&lt;/li&gt;
&lt;li&gt;Coroutine objects&lt;/li&gt;
&lt;li&gt;Async generator objects&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All 3 share the same subset of fields used in generators, and have similar behaviors:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/generators.536b1404195a.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/generators.536b1404195a.png&quot; width=&quot;612&quot; height=&quot;264&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/generators.536b1404195a.png&amp;amp;w=153&amp;amp;sig=665718d32fbb9081b7983085eaeb6de7437ed6b6 153w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/generators.536b1404195a.png&amp;amp;w=306&amp;amp;sig=05fff378d8474cff821fbd585c9a57c5c5c51283 306w, https://files.realpython.com/media/generators.536b1404195a.png 612w&quot; sizes=&quot;75vw&quot; alt=&quot;Structure of generator types&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Focusing first on generators, you can see the fields:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gi_frame&lt;/code&gt; linking to a &lt;code&gt;PyFrameObject&lt;/code&gt; for the generator, earlier in the execution chapter, we explored the use of locals and globals inside a frame&amp;rsquo;s value stack. This is how generators remember the last value of local variables since the frame is persistent between calls&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gi_running&lt;/code&gt; set to 0 or 1 if the generator is currently running&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gi_code&lt;/code&gt; linking to a &lt;code&gt;PyCodeObject&lt;/code&gt; with the compiled function that yielded the generator so that it can be called again&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gi_weakreflist&lt;/code&gt; linking to a list of weak references to objects inside the generator function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gi_name&lt;/code&gt; as the name of the generator&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gi_qualname&lt;/code&gt; as the qualified name of the generator&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gi_exc_state&lt;/code&gt; as a tuple of exception data if the generator call raises an exception&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The coroutine and &lt;a href=&quot;https://realpython.com/async-io-python/#other-features-async-for-and-async-generators-comprehensions&quot;&gt;async generators&lt;/a&gt; have the same fields but prepended with &lt;code&gt;cr&lt;/code&gt; and &lt;code&gt;ag&lt;/code&gt; respectively.&lt;/p&gt;
&lt;p&gt;If you call &lt;code&gt;__next__()&lt;/code&gt; on the generator object, the next value is yielded until eventually a &lt;code&gt;StopIteration&lt;/code&gt; is raised:&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;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;__next__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;__next__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;__next__&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;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;__next__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;__next__&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;StopIteration&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each time &lt;code&gt;__next__()&lt;/code&gt; is called, the code object inside the generators &lt;code&gt;gi_code&lt;/code&gt; field is executed as a new frame and the return value is pushed to the value stack.&lt;/p&gt;
&lt;p&gt;You can also see that &lt;code&gt;gi_code&lt;/code&gt; is the compiled code object for the generator function by importing the &lt;code&gt;dis&lt;/code&gt; module and disassembling the bytecode inside:&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;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;p&quot;&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;dis&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disco&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  2           0 LOAD_CONST               1 (1)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;              2 LOAD_CONST               2 (2)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;              4 LOAD_CONST               3 (3)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;              6 LOAD_CONST               4 (4)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;              8 BUILD_LIST               4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             10 STORE_FAST               0 (l)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  3          12 SETUP_LOOP              18 (to 32)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             14 LOAD_FAST                0 (l)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             16 GET_ITER&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;        &amp;gt;&amp;gt;   18 FOR_ITER                10 (to 30)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             20 STORE_FAST               1 (i)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  4          22 LOAD_FAST                1 (i)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             24 YIELD_VALUE&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             26 POP_TOP&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             28 JUMP_ABSOLUTE           18&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;        &amp;gt;&amp;gt;   30 POP_BLOCK&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;        &amp;gt;&amp;gt;   32 LOAD_CONST               0 (None)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             34 RETURN_VALUE&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Whenever &lt;code&gt;__next__()&lt;/code&gt; is called on a generator object, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/genobject.c#L541&quot;&gt;&lt;code&gt;gen_iternext()&lt;/code&gt;&lt;/a&gt; is called with the generator instance, which immediately calls &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/genobject.c#L153&quot;&gt;&lt;code&gt;gen_send_ex()&lt;/code&gt;&lt;/a&gt; inside &lt;code&gt;Objects/genobject.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gen_send_ex()&lt;/code&gt; is the function that converts a generator object into the next yielded result. You&amp;rsquo;ll see many similarities with the way frames are constructed in &lt;code&gt;Python/ceval.c&lt;/code&gt; from a code object as these functions have similar tasks.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;gen_send_ex()&lt;/code&gt; function is shared with generators, coroutines, and async generators and has the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The current thread state is fetched&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The frame object from the generator object is fetched&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the generator is running when &lt;code&gt;__next__()&lt;/code&gt; was called, raise a &lt;code&gt;ValueError&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the frame inside the generator is at the top of the stack:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the case of a coroutine, if the coroutine is not already marked as closing, a &lt;code&gt;RuntimeError&lt;/code&gt; is raised&lt;/li&gt;
&lt;li&gt;If this is an async generator, raise a &lt;code&gt;StopAsyncIteration&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For a standard generator, a &lt;code&gt;StopIteration&lt;/code&gt; is raised.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the last instruction in the frame (&lt;code&gt;f-&amp;gt;f_lasti&lt;/code&gt;) is still -1 because it has just been started, and this is a coroutine or async generator, then a non-None value can&amp;rsquo;t be passed as an argument, so an exception is raised&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Else, this is the first time it&amp;rsquo;s being called, and arguments are allowed. The value of the argument is pushed to the frame&amp;rsquo;s value stack&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;f_back&lt;/code&gt; field of the frame is the caller to which return values are sent, so this is set to the current frame in the thread. This means that the return value is sent to the caller, not the creator of the generator&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The generator is marked as running&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The last exception in the generator&amp;rsquo;s exception info is copied from the last exception in the thread state&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The thread state exception info is set to the address of the generator&amp;rsquo;s exception info. This means that if the caller enters a breakpoint around the execution of a generator, the stack trace goes through the generator and the offending code is clear&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The frame inside the generator is executed within the &lt;code&gt;Python/ceval.c&lt;/code&gt; main execution loop, and the value returned&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The thread state last exception is reset to the value before the frame was called&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The generator is marked as not running&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The following cases then match the return value and any exceptions thrown by the call to the generator. Remember that generators should raise a &lt;code&gt;StopIteration&lt;/code&gt; when they are exhausted, either manually, or by not yielding a value. Coroutines and async generators should not:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If no result was returned from the frame, raise a &lt;code&gt;StopIteration&lt;/code&gt; for generators and &lt;code&gt;StopAsyncIteration&lt;/code&gt; for async generators&lt;/li&gt;
&lt;li&gt;If a &lt;code&gt;StopIteration&lt;/code&gt; was explicitly raised, but this is a coroutine or an async generator, raise a &lt;code&gt;RuntimeError&lt;/code&gt; as this is not allowed&lt;/li&gt;
&lt;li&gt;If a &lt;code&gt;StopAsyncIteration&lt;/code&gt; was explicitly raised and this is an async generator, raise a &lt;code&gt;RuntimeError&lt;/code&gt;, as this is not allowed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lastly, the result is returned back to the caller of &lt;code&gt;__next__()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;gen_send_ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyGenObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&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;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;closing&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;n&quot;&gt;PyThreadState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyThreadState_GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// 1.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;PyFrameObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;// 2.&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&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;hll&quot;&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;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_running&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;// 3.&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;generator already executing&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyCoro_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;coroutine already executing&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;else&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;PyAsyncGen_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;async generator already executing&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_ValueError&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;k&quot;&gt;if&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;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_stacktop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;// 4.&lt;/span&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;PyCoro_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;closing&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;cm&quot;&gt;/* `gen` is an exhausted coroutine: raise an error,&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;               except when called from gen_close(), which should&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;               always be a silent method. */&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;            &lt;span class=&quot;n&quot;&gt;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;                &lt;span class=&quot;n&quot;&gt;PyExc_RuntimeError&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;s&quot;&gt;&amp;quot;cannot reuse already awaited coroutine&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 4a.&lt;/span&gt;
&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;k&quot;&gt;if&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;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exc&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;cm&quot;&gt;/* `gen` is an exhausted generator:&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;               only set exception if called from send(). */&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;PyAsyncGen_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;n&quot;&gt;PyErr_SetNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_StopAsyncIteration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 4b.&lt;/span&gt;
&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;hll&quot;&gt;                &lt;span class=&quot;n&quot;&gt;PyErr_SetNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_StopIteration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// 4c.&lt;/span&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;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&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;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_lasti&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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&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;arg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_None&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;// 5.&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;can&amp;#39;t send non-None value to a &amp;quot;&lt;/span&gt;
                              &lt;span class=&quot;s&quot;&gt;&amp;quot;just-started generator&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyCoro_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NON_INIT_CORO_MSG&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;else&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;PyAsyncGen_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;can&amp;#39;t send non-None value to a &amp;quot;&lt;/span&gt;
                      &lt;span class=&quot;s&quot;&gt;&amp;quot;just-started async generator&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_TypeError&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 6.&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;cm&quot;&gt;/* Push arg onto the frame&amp;#39;s value stack */&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;arg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;arg&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_INCREF&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;o&quot;&gt;*&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;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_stacktop&lt;/span&gt;&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;n&quot;&gt;result&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;cm&quot;&gt;/* Generators always return to their most recent caller, not&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * necessarily their creator. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_XINCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;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;assert&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;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_back&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_back&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;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;c1&quot;&gt;// 7.&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_running&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;c1&quot;&gt;// 8.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_exc_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;previous_item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exc_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 9.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exc_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_exc_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;// 10.&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;n&quot;&gt;PyEval_EvalFrameEx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;// 11.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exc_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_exc_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;previous_item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 12.&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_exc_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;previous_item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_running&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                &lt;span class=&quot;c1&quot;&gt;// 13.&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* Don&amp;#39;t keep the reference to f_back any longer than necessary.  It&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * may keep a chain of frames alive or it could create a reference&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * cycle. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&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;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_back&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;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;Py_CLEAR&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;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_back&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* If the generator just returned (as opposed to yielding), signal&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * that the generator is exhausted. */&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_stacktop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;// 14a.&lt;/span&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;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_None&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;cm&quot;&gt;/* Delay exception instantiation if we can */&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;PyAsyncGen_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;PyErr_SetNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_StopAsyncIteration&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;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;PyErr_SetNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_StopIteration&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;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;cm&quot;&gt;/* Async generators cannot return anything but None */&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;assert&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;PyAsyncGen_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_PyGen_SetStopIterationValue&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;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Py_CLEAR&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&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;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyErr_ExceptionMatches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_StopIteration&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;// 14b.&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;generator raised StopIteration&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyCoro_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;coroutine raised StopIteration&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;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyAsyncGen_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;async generator raised StopIteration&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_PyErr_FormatFromCause&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_RuntimeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;%s&amp;quot;&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;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyAsyncGen_CheckExact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;             &lt;span class=&quot;n&quot;&gt;PyErr_ExceptionMatches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_StopAsyncIteration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 14c.&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/* code in `gen` raised a StopAsyncIteration error:&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;           raise a RuntimeError.&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;        */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;async generator raised StopAsyncIteration&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_PyErr_FormatFromCause&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_RuntimeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;%s&amp;quot;&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;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;k&quot;&gt;return&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;c1&quot;&gt;// 15.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Going back to the evaluation of code objects whenever a function or module is called, there was a special case for generators, coroutines, and async generators in &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/ceval.c#L4045&quot;&gt;&lt;code&gt;_PyEval_EvalCodeWithName()&lt;/code&gt;&lt;/a&gt;. This function checks for the &lt;code&gt;CO_GENERATOR&lt;/code&gt;, &lt;code&gt;CO_COROUTINE&lt;/code&gt;, and &lt;code&gt;CO_ASYNC_GENERATOR&lt;/code&gt; flags on the code object.&lt;/p&gt;
&lt;p&gt;When a new coroutine is created using &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/genobject.c#L1152&quot;&gt;&lt;code&gt;PyCoro_New()&lt;/code&gt;&lt;/a&gt;, a new async generator is created with &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/genobject.c#L1428&quot;&gt;&lt;code&gt;PyAsyncGen_New()&lt;/code&gt;&lt;/a&gt; or a generator with &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/genobject.c#L811&quot;&gt;&lt;code&gt;PyGen_NewWithQualName()&lt;/code&gt;&lt;/a&gt;. These objects are returned early instead of returning an evaluated frame, which is why you get a generator object after calling a function with a yield statement:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;_PyEval_EvalCodeWithName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&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;cm&quot;&gt;/* Handle generator/coroutine/asynchronous generator */&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CO_GENERATOR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_COROUTINE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_ASYNC_GENERATOR&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;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coro_wrapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tstate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coroutine_wrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_coro&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_COROUTINE&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;cm&quot;&gt;/* Create a new generator that owns the ready to run frame&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;         * and return that as the value. */&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;is_coro&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;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCoro_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualname&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;else&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;co&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CO_ASYNC_GENERATOR&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;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyAsyncGen_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualname&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;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyGen_NewWithQualName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualname&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gen&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;The flags in the code object were injected by the compiler after traversing the AST and seeing the &lt;code&gt;yield&lt;/code&gt; or &lt;code&gt;yield from&lt;/code&gt; statements or seeing the &lt;code&gt;coroutine&lt;/code&gt; decorator.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PyGen_NewWithQualName()&lt;/code&gt; will call &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Objects/genobject.c#L778&quot;&gt;&lt;code&gt;gen_new_with_qualname()&lt;/code&gt;&lt;/a&gt; with the generated frame and then create the &lt;code&gt;PyGenObject&lt;/code&gt; with &lt;code&gt;NULL&lt;/code&gt; values and the compiled code object:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;gen_new_with_qualname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyTypeObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyFrameObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qualname&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;PyGenObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject_GC_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyGenObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&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;gen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;Py_DECREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_gen&lt;/span&gt; &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;PyObject&lt;/span&gt; &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;gen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_INCREF&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;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_code&lt;/span&gt; &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;PyObject&lt;/span&gt; &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;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_running&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_weakreflist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_exc_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exc_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_exc_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exc_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_exc_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exc_traceback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_exc_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;previous_item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_name&lt;/span&gt; &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;PyCodeObject&lt;/span&gt; &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;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_code&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;co_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_INCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_name&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;qualname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_qualname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualname&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;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_qualname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Py_INCREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gi_qualname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_PyObject_GC_TRACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &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;gen&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;Bringing this all together you can see how the generator expression is a powerful syntax where a single keyword, &lt;code&gt;yield&lt;/code&gt; triggers a whole flow to create a unique object, copy a compiled code object as a property, set a frame, and store a list of variables in the local scope.&lt;/p&gt;
&lt;p&gt;To the user of the generator expression, this all seems like magic, but under the covers it&amp;rsquo;s not &lt;em&gt;that&lt;/em&gt; complex.&lt;/p&gt;
&lt;h3 id=&quot;conclusion_4&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Now that you understand how some built-in types, you can explore other types. &lt;/p&gt;
&lt;p&gt;When exploring Python classes, it is important to remember there are built-in types, written in C and classes inheriting from those types, written in Python or C.&lt;/p&gt;
&lt;p&gt;Some libraries have types written in C instead of inheriting from the built-in types. One example is &lt;code&gt;numpy&lt;/code&gt;, a library for numeric arrays. The &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html&quot;&gt;&lt;code&gt;nparray&lt;/code&gt;&lt;/a&gt; type is written in C, is highly efficient and performant.&lt;/p&gt;
&lt;p&gt;In the next Part, we will explore the classes and functions defined in the standard library.&lt;/p&gt;
&lt;h2 h1=&quot;h1&quot; id=&quot;part-5-the-cpython-standard-library&quot;&gt;Part 5: The CPython Standard Library&lt;/h2&gt;
&lt;p&gt;Python has always come &amp;ldquo;batteries included.&amp;rdquo; This statement means that with a standard CPython distribution, there are libraries for working with files, threads, networks, web sites, music, keyboards, screens, text, and a whole manner of utilities.&lt;/p&gt;
&lt;p&gt;Some of the batteries that come with CPython are more like AA batteries. They&amp;rsquo;re useful for everything, like the &lt;code&gt;collections&lt;/code&gt; module and the &lt;code&gt;sys&lt;/code&gt; module. Some of them are a bit more obscure, like a small watch battery that you never know when it might come in useful.&lt;/p&gt;
&lt;p&gt;There are 2 types of modules in the CPython standard library:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Those written in pure Python that provides a utility&lt;/li&gt;
&lt;li&gt;Those written in C with Python wrappers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will explore both types.&lt;/p&gt;
&lt;h3 id=&quot;python-modules&quot;&gt;Python Modules&lt;/h3&gt;
&lt;p&gt;The modules written in pure Python are all located in the &lt;code&gt;Lib/&lt;/code&gt; directory in the source code. Some of the larger modules have submodules in subfolders, like the &lt;code&gt;email&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;An easy module to look at would be the &lt;code&gt;colorsys&lt;/code&gt; module. It&amp;rsquo;s only a few hundred lines of Python code. You may not have come across it before. The &lt;code&gt;colorsys&lt;/code&gt; module has some utility functions for converting color scales.&lt;/p&gt;
&lt;p&gt;When you install a Python distribution from source, standard library modules are copied from the &lt;code&gt;Lib&lt;/code&gt; folder into the distribution folder. This folder is always part of your path when you start Python, so you can &lt;code&gt;import&lt;/code&gt; the modules without having to worry about where they&amp;rsquo;re located. &lt;/p&gt;
&lt;p&gt;For 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;colorsys&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colorsys&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;module &amp;#39;colorsys&amp;#39; from &amp;#39;/usr/shared/lib/python3.7/colorsys.py&amp;#39;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colorsys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rgb_to_hls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&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;go&quot;&gt;(0.0, 127.5, -1.007905138339921) &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can see the source code of &lt;code&gt;rgb_to_hls()&lt;/code&gt; inside &lt;code&gt;Lib/colorsys.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# HLS: Hue, Luminance, Saturation&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# H: position in the spectrum&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# L: color lightness&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# S: color saturation&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rgb_to_hls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&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;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;maxc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&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;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;minc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&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;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# XXX Can optimize (maxc+minc) and (maxc-minc)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &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;minc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxc&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;2.0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxc&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;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&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;n&quot;&gt;s&lt;/span&gt; &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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minc&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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minc&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;s&lt;/span&gt; &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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minc&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;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gc&lt;/span&gt; &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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bc&lt;/span&gt; &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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&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;maxc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minc&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;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gc&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bc&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;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;6.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There&amp;rsquo;s nothing special about this function, it&amp;rsquo;s just standard Python. You&amp;rsquo;ll find similar things with all of the pure Python standard library modules. They&amp;rsquo;re just written in plain Python, well laid out and easy to understand. You may even spot improvements or bugs, so you can make changes to them and contribute it to the Python distribution. We&amp;rsquo;ll cover that toward the end of this article.&lt;/p&gt;
&lt;h3 id=&quot;python-and-c-modules&quot;&gt;Python and C Modules&lt;/h3&gt;
&lt;p&gt;The remainder of modules are written in C, or a combination or Python and C. The source code for these is in &lt;code&gt;Lib/&lt;/code&gt; for the Python component, and &lt;code&gt;Modules/&lt;/code&gt; for the C component. There are two exceptions to this rule, the &lt;code&gt;sys&lt;/code&gt; module, found in &lt;code&gt;Python/sysmodule.c&lt;/code&gt; and the &lt;code&gt;__builtins__&lt;/code&gt; module, found in &lt;code&gt;Python/bltinmodule.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Python will &lt;code&gt;import * from __builtins__&lt;/code&gt; when an interpreter is instantiated, so all of the functions like &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/bltinmodule.c#L1821&quot;&gt;&lt;code&gt;print()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/bltinmodule.c#L688&quot;&gt;&lt;code&gt;chr()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Python/bltinmodule.c#L672&quot;&gt;&lt;code&gt;format()&lt;/code&gt;&lt;/a&gt;, etc. are found within &lt;code&gt;Python/bltinmodule.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because the &lt;code&gt;sys&lt;/code&gt; module is so specific to the interpreter and the internals of CPython, that is found inside the &lt;code&gt;Python&lt;/code&gt; directly. It is also marked as an &amp;ldquo;implementation detail&amp;rdquo; of CPython and not found in other distributions.&lt;/p&gt;
&lt;p&gt;The built-in &lt;code&gt;print()&lt;/code&gt; function was probably the first thing you learned to do in Python. So what happens when you type &lt;code&gt;print(&quot;hello world!&quot;)&lt;/code&gt;?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The argument &lt;code&gt;&quot;hello world&quot;&lt;/code&gt; was converted from a string constant to a &lt;code&gt;PyUnicodeObject&lt;/code&gt; by the compiler&lt;/li&gt;
&lt;li&gt;&lt;code&gt;builtin_print()&lt;/code&gt; was executed with 1 argument, and NULL &lt;code&gt;kwnames&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;file&lt;/code&gt; variable is set to &lt;code&gt;PyId_stdout&lt;/code&gt;, the system&amp;rsquo;s &lt;code&gt;stdout&lt;/code&gt; handle&lt;/li&gt;
&lt;li&gt;Each argument is sent to &lt;code&gt;file&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A line break, &lt;code&gt;\n&lt;/code&gt; is sent to &lt;code&gt;file&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;builtin_print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_ssize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwnames&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_None&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;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PySys_GetObjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyId_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&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;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&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;0&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;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&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;p&quot;&gt;)&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;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;p&quot;&gt;)&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;sep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyFile_WriteString&lt;/span&gt;&lt;span class=&quot;p&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;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyFile_WriteObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                         &lt;span class=&quot;n&quot;&gt;Py_PRINT_RAW&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;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyFile_WriteObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;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;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_PRINT_RAW&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;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&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;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyFile_WriteString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyFile_WriteObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_PRINT_RAW&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;Py_RETURN_NONE&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 contents of some modules written in C expose operating system functions. Because the CPython source code needs to compile to macOS, Windows, Linux, and other *nix-based operating systems, there are some special cases.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;time&lt;/code&gt; module is a good example. The way that Windows keeps and stores time in the Operating System is fundamentally different than Linux and macOS. This is one of the reasons why the accuracy of the clock functions differs &lt;a href=&quot;https://docs.python.org/3/library/time.html#time.clock_gettime_ns&quot;&gt;between operating systems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;Modules/timemodule.c&lt;/code&gt;, the operating system time functions for Unix-based systems are imported from &lt;code&gt;&amp;lt;sys/times.h&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#ifdef HAVE_SYS_TIMES_H&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;sys/times.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef MS_WINDOWS&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define WIN32_LEAN_AND_MEAN&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;windows.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;quot;pythread.h&amp;quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* MS_WINDOWS */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Later in the file, &lt;code&gt;time_process_time_ns()&lt;/code&gt; is defined as a wrapper for &lt;code&gt;_PyTime_GetProcessTimeWithInfo()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;time_process_time_ns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unused&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;_PyTime_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_PyTime_GetProcessTimeWithInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_PyTime_AsNanosecondsObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/d93605de7232da5e6a182fd1d5c220639e900159/Modules/timemodule.c#L1120&quot;&gt;&lt;code&gt;_PyTime_GetProcessTimeWithInfo()&lt;/code&gt;&lt;/a&gt; is implemented multiple different ways in the source code, but only certain parts are compiled into the binary for the module, depending on the operating system. Windows systems will call &lt;code&gt;GetProcessTimes()&lt;/code&gt; and Unix systems will call &lt;code&gt;clock_gettime()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Other modules that have multiple implementations for the same API are &lt;a href=&quot;https://realpython.com/intro-to-python-threading/&quot;&gt;the threading module&lt;/a&gt;, the file system module, and the networking modules. Because the Operating Systems behave differently, the CPython source code implements the same behavior as best as it can and exposes it using a consistent, abstracted API.&lt;/p&gt;
&lt;h3 id=&quot;the-cpython-regression-test-suite&quot;&gt;The CPython Regression Test Suite&lt;/h3&gt;
&lt;p&gt;CPython has a robust and extensive test suite covering the core interpreter, the standard library, the tooling and distribution for both Windows and Linux/macOS.&lt;/p&gt;
&lt;p&gt;The test suite is located in &lt;code&gt;Lib/test&lt;/code&gt; and written almost entirely in Python.&lt;/p&gt;
&lt;p&gt;The full test suite is a Python package, so can be run using the Python interpreter that you&amp;rsquo;ve compiled. Change directory to the &lt;code&gt;Lib&lt;/code&gt; directory and run &lt;code&gt;python -m test -j2&lt;/code&gt;, where &lt;code&gt;j2&lt;/code&gt; means to use 2 CPUs.&lt;/p&gt;
&lt;p&gt;On Windows use the &lt;code&gt;rt.bat&lt;/code&gt; script inside the PCBuild folder, ensuring that you have built the &lt;strong&gt;Release&lt;/strong&gt; configuration from Visual Studio in advance:&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; PCbuild
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; rt.bat -q

&lt;span class=&quot;go&quot;&gt;C:\repos\cpython\PCbuild&amp;gt;&amp;quot;C:\repos\cpython\PCbuild\win32\python.exe&amp;quot;  -u -Wd -E -bb -m test&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== CPython 3.8.0b4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== Windows-10-10.0.17134-SP0 little-endian&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== cwd: C:\repos\cpython\build\test_python_2784&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== CPU count: 2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== encodings: locale=cp1252, FS=utf-8&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Run tests sequentially&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 [  1/420] test_grammar&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 [  2/420] test_opcodes&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 [  3/420] test_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 [  4/420] test_builtin&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On Linux:&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; Lib
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ../python -m &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; -j2   
&lt;span class=&quot;go&quot;&gt;== CPython 3.8.0b4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== macOS-10.14.3-x86_64-i386-64bit little-endian&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== cwd: /Users/anthonyshaw/cpython/build/test_python_23399&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== CPU count: 4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== encodings: locale=UTF-8, FS=utf-8&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Run tests in parallel using 2 child processes&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 load avg: 2.14 [  1/420] test_opcodes passed&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 load avg: 2.14 [  2/420] test_grammar passed&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On macOS:&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; Lib
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ../python.exe -m &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; -j2   
&lt;span class=&quot;go&quot;&gt;== CPython 3.8.0b4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== macOS-10.14.3-x86_64-i386-64bit little-endian&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== cwd: /Users/anthonyshaw/cpython/build/test_python_23399&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== CPU count: 4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== encodings: locale=UTF-8, FS=utf-8&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Run tests in parallel using 2 child processes&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 load avg: 2.14 [  1/420] test_opcodes passed&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 load avg: 2.14 [  2/420] test_grammar passed&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Some tests require certain flags; otherwise they are skipped. For example, many of the IDLE tests require a GUI.&lt;/p&gt;
&lt;p&gt;To see a list of test suites in the configuration, use the &lt;code&gt;--list-tests&lt;/code&gt; flag:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ../python.exe -m &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; --list-tests

&lt;span class=&quot;go&quot;&gt;test_grammar&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_opcodes&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_builtin&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_exceptions&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can run specific tests by providing the test suite as the first argument:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ../python.exe -m &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; test_webbrowser

&lt;span class=&quot;go&quot;&gt;Run tests sequentially&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 load avg: 2.74 [1/1] test_webbrowser&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;== Tests result: SUCCESS ==&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;1 test OK.&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Total duration: 117 ms&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Tests result: SUCCESS&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also see a detailed list of tests that were executed with the result using the &lt;code&gt;-v&lt;/code&gt; argument:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ../python.exe -m &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; test_webbrowser -v

&lt;span class=&quot;go&quot;&gt;== CPython 3.8.0b4 &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== macOS-10.14.3-x86_64-i386-64bit little-endian&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== cwd: /Users/anthonyshaw/cpython/build/test_python_24562&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== CPU count: 4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;== encodings: locale=UTF-8, FS=utf-8&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Run tests sequentially&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0:00:00 load avg: 2.36 [1/1] test_webbrowser&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_open (test.test_webbrowser.BackgroundBrowserCommandTest) ... ok&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_register (test.test_webbrowser.BrowserRegistrationTest) ... ok&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_register_default (test.test_webbrowser.BrowserRegistrationTest) ... ok&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_register_preferred (test.test_webbrowser.BrowserRegistrationTest) ... ok&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_open (test.test_webbrowser.ChromeCommandTest) ... ok&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_open_new (test.test_webbrowser.ChromeCommandTest) ... ok&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;test_open_with_autoraise_false (test.test_webbrowser.OperaCommandTest) ... ok&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;----------------------------------------------------------------------&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Ran 34 tests in 0.056s&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;OK (skipped=2)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;== Tests result: SUCCESS ==&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;1 test OK.&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Total duration: 134 ms&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Tests result: SUCCESS&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Understanding how to use the test suite and checking the state of the version you have compiled is very important if you wish to make changes to CPython. Before you start making changes, you should run the whole test suite and make sure everything is passing.&lt;/p&gt;
&lt;h3 id=&quot;installing-a-custom-version&quot;&gt;Installing a Custom Version&lt;/h3&gt;
&lt;p&gt;From your source repository, if you&amp;rsquo;re happy with your changes and want to use them inside your system, you can install it as a custom version.&lt;/p&gt;
&lt;p&gt;For macOS and Linux, you can use the &lt;code&gt;altinstall&lt;/code&gt; command, which won&amp;rsquo;t create symlinks for &lt;code&gt;python3&lt;/code&gt; and install a standalone version:&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; make altinstall
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For Windows, you have to change the build configuration from &lt;code&gt;Debug&lt;/code&gt; to &lt;code&gt;Release&lt;/code&gt;, then copy the packaged binaries to a directory on your computer which is part of the system path.&lt;/p&gt;
&lt;h2 id=&quot;the-cpython-source-code-conclusion&quot;&gt;The CPython Source Code: Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations, you made it! Did your tea get cold? Make yourself another cup. You&amp;rsquo;ve earned it.&lt;/p&gt;
&lt;p&gt;Now that you&amp;rsquo;ve seen the CPython source code, the modules, the compiler, and the tooling, you may wish to make some changes and contribute them back to the Python ecosystem.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://devguide.python.org/&quot;&gt;official dev guide&lt;/a&gt; contains plenty of resources for beginners. You&amp;rsquo;ve already taken the first step, to understand the source, knowing how to change, compile, and test the CPython applications.&lt;/p&gt;
&lt;p&gt;Think back to all the things you&amp;rsquo;ve learned about CPython over this article. All the pieces of magic to which you&amp;rsquo;ve learned the secrets. The journey doesn&amp;rsquo;t stop here. &lt;/p&gt;
&lt;p&gt;This might be a good time to learn more about Python and C. Who knows: you could be contributing more and more to the CPython project!&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 Histogram Plotting: NumPy, Matplotlib, Pandas &amp; Seaborn</title>
      <id>https://realpython.com/courses/python-histograms/</id>
      <link href="https://realpython.com/courses/python-histograms/"/>
      <updated>2019-08-20T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll be equipped to make production-quality, presentation-ready Python histogram plots with a range of choices and features. It&#39;s your one-stop shop for constructing and manipulating histograms with Python&#39;s scientific stack.</summary>
      <content type="html">
        &lt;p&gt;In this course, you&amp;rsquo;ll be equipped to make production-quality, presentation-ready Python histogram plots with a range of choices and features.&lt;/p&gt;
&lt;p&gt;If you have introductory to intermediate knowledge in Python and statistics, then you can use this article as a one-stop shop for building and plotting histograms in Python using libraries from its scientific stack, including NumPy, Matplotlib, Pandas, and Seaborn.&lt;/p&gt;
&lt;p&gt;A histogram is a great tool for quickly assessing a &lt;a href=&quot;https://en.wikipedia.org/wiki/Probability_distribution&quot;&gt;probability distribution&lt;/a&gt; that is intuitively understood by almost any audience.  Python offers a handful of different options for building and plotting histograms.  Most people know a histogram by its graphical representation, which is similar to a bar graph:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/commute_times.621e5b1ce062.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/commute_times.621e5b1ce062.png&quot; width=&quot;1152&quot; height=&quot;888&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/commute_times.621e5b1ce062.png&amp;amp;w=288&amp;amp;sig=408f56b07d4fb71d47171405f51e3cb58a7e6cc2 288w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/commute_times.621e5b1ce062.png&amp;amp;w=576&amp;amp;sig=a2b0324c81a7cd89fe7ceaacdcd4ae797ad1a587 576w, https://files.realpython.com/media/commute_times.621e5b1ce062.png 1152w&quot; sizes=&quot;75vw&quot; alt=&quot;Histogram of commute times for 1000 commuters&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This course will guide you through creating plots like the one above as well as more complex ones.  Here&amp;rsquo;s what you&amp;rsquo;ll cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Building histograms in pure Python, without use of third party libraries&lt;/li&gt;
&lt;li&gt;Constructing histograms with NumPy to summarize the underlying data&lt;/li&gt;
&lt;li&gt;Plotting the resulting histogram with Matplotlib, Pandas, and Seaborn&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; Short on time? &lt;a href=&quot;https://realpython.com/optins/view/histograms-cheatsheet/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-histograms-cheatsheet&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a free two-page Python histograms cheat sheet&lt;/a&gt; that summarizes the techniques explained in this tutorial.&lt;/p&gt;&lt;/div&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>How to Make a Discord Bot in Python</title>
      <id>https://realpython.com/how-to-make-a-discord-bot-python/</id>
      <link href="https://realpython.com/how-to-make-a-discord-bot-python/"/>
      <updated>2019-08-19T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how to make a Discord bot in Python and interact with several APIs. You&#39;ll learn how to handle events, accept commands, validate and verify input, and all the basics that can help you create useful and exciting automations!</summary>
      <content type="html">
        &lt;p&gt;In a world where video games are so important to so many people, communication and community around games are vital. Discord offers both of those and more in one well-designed package. In this tutorial, you&amp;rsquo;ll learn how to make a Discord bot in Python so that you can make the most of this fantastic platform.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this article you&amp;rsquo;ll learn:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What Discord is and why it&amp;rsquo;s so valuable&lt;/li&gt;
&lt;li&gt;How to make a Discord bot through the Developer Portal&lt;/li&gt;
&lt;li&gt;How to create Discord connections&lt;/li&gt;
&lt;li&gt;How to handle events&lt;/li&gt;
&lt;li&gt;How to accept commands and validate assumptions&lt;/li&gt;
&lt;li&gt;How to interact with various Discord APIs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You&amp;rsquo;ll begin by learning what Discord is and why it&amp;rsquo;s valuable.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;what-is-discord&quot;&gt;What Is Discord?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://discordapp.com/&quot;&gt;Discord&lt;/a&gt; is a voice and text communication platform for gamers.&lt;/p&gt;
&lt;p&gt;Players, streamers, and developers use Discord to discuss games, answer questions, chat while they play, and much more. It even has a game store, complete with critical reviews and a subscription service. It is nearly a one-stop shop for gaming communities.&lt;/p&gt;
&lt;p&gt;While there are many things you can build using Discord&amp;rsquo;s &lt;a href=&quot;https://discordapp.com/developers/docs/intro&quot;&gt;APIs&lt;/a&gt;, this tutorial will focus on a particular learning outcome: how to make a Discord bot in Python.&lt;/p&gt;
&lt;h2 id=&quot;what-is-a-bot&quot;&gt;What Is a Bot?&lt;/h2&gt;
&lt;p&gt;Discord is growing in popularity. As such, automated processes, such as banning inappropriate users and reacting to user requests are vital for a community to thrive and grow.&lt;/p&gt;
&lt;p&gt;Automated programs that look and act like users and automatically respond to events and commands on Discord are called &lt;strong&gt;bot users&lt;/strong&gt;. Discord bot users (or just &lt;strong&gt;bots&lt;/strong&gt;) have nearly &lt;a href=&quot;https://discordbots.org&quot;&gt;unlimited applications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example, let&amp;rsquo;s say you&amp;rsquo;re managing a new Discord guild and a user joins for the very first time. Excited, you may personally reach out to that user and welcome them to your community. You might also tell them about your channels or ask them to introduce themselves.&lt;/p&gt;
&lt;p&gt;The user feels welcomed and enjoys the discussions that happen in your guild and they, in turn, invite friends.&lt;/p&gt;
&lt;p&gt;Over time, your community grows so big that it&amp;rsquo;s no longer feasible to personally reach out to each new member, but you still want to send them something to recognize them as a new member of the guild.&lt;/p&gt;
&lt;p&gt;With a bot, it&amp;rsquo;s possible to automatically react to the new member joining your guild. You can even customize its behavior based on context and control how it interacts with each new user.&lt;/p&gt;
&lt;p&gt;This is great, but it&amp;rsquo;s only one small example of how a bot can be useful. There are so many opportunities for you to be creative with bots, once you know how to make them.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Although Discord allows you to create bots that deal with voice communication, this article will stick to the text side of the service.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;There are two key steps when you&amp;rsquo;re creating a bot:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create the bot user on Discord and register it with a guild.&lt;/li&gt;
&lt;li&gt;Write code that uses Discord&amp;rsquo;s APIs and implements your bot&amp;rsquo;s behaviors.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the next section, you&amp;rsquo;ll learn how to make a Discord bot in Discord&amp;rsquo;s &lt;a href=&quot;https://discordapp.com/developers/applications&quot;&gt;Developer Portal&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-to-make-a-discord-bot-in-the-developer-portal&quot;&gt;How to Make a Discord Bot in the Developer Portal&lt;/h2&gt;
&lt;p&gt;Before you can dive into any Python code to handle events and create exciting automations, you need to first create a few Discord components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An account&lt;/li&gt;
&lt;li&gt;An application&lt;/li&gt;
&lt;li&gt;A bot&lt;/li&gt;
&lt;li&gt;A guild&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You&amp;rsquo;ll learn more about each piece in the following sections.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve created all of these components, you&amp;rsquo;ll tie them together by registering your bot with your guild.&lt;/p&gt;
&lt;p&gt;You can get started by heading to Discord&amp;rsquo;s &lt;a href=&quot;http://discordapp.com/developers/applications&quot;&gt;Developer Portal&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;creating-a-discord-account&quot;&gt;Creating a Discord Account&lt;/h3&gt;
&lt;p&gt;The first thing you&amp;rsquo;ll see is a landing page where you&amp;rsquo;ll need to either login, if you have an existing account, or create a new account:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-register-user.41a9c2bc4db9.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/discord-bot-register-user.41a9c2bc4db9.png&quot; width=&quot;3024&quot; height=&quot;1762&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-register-user.41a9c2bc4db9.png&amp;amp;w=756&amp;amp;sig=6d39dcc4f6fc11eb5de6e2b457fc387d04dcb138 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-register-user.41a9c2bc4db9.png&amp;amp;w=1512&amp;amp;sig=454c3dfb7830bfefbd4fc267e92af61669936082 1512w, https://files.realpython.com/media/discord-bot-register-user.41a9c2bc4db9.png 3024w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Account Login Screen&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you need to create a new account, then click on the &lt;em&gt;Register&lt;/em&gt; button below &lt;em&gt;Login&lt;/em&gt; and enter your account information.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; You&amp;rsquo;ll need to verify your email before you&amp;rsquo;re able to move on.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Once you&amp;rsquo;re finished, you&amp;rsquo;ll be redirected to the Developer Portal home page, where you&amp;rsquo;ll create your application.&lt;/p&gt;
&lt;h3 id=&quot;creating-an-application&quot;&gt;Creating an Application&lt;/h3&gt;
&lt;p&gt;An &lt;strong&gt;application&lt;/strong&gt; allows you to interact with Discord&amp;rsquo;s APIs by  providing authentication tokens, designating permissions, and so on.&lt;/p&gt;
&lt;p&gt;To create a new application, select &lt;em&gt;New Application&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-new-app.40b4a51bb57d.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/discord-bot-new-app.40b4a51bb57d.png&quot; width=&quot;3024&quot; height=&quot;1765&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-new-app.40b4a51bb57d.png&amp;amp;w=756&amp;amp;sig=094b6a170204052aa3e03749c858002b90ccb1bd 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-new-app.40b4a51bb57d.png&amp;amp;w=1512&amp;amp;sig=fb20c2f10526eafc64138f33c8e8f08e5c895d57 1512w, https://files.realpython.com/media/discord-bot-new-app.40b4a51bb57d.png 3024w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: My Applications Screen&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next, you&amp;rsquo;ll be prompted to name your application. Select a name and click &lt;em&gt;Create&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-name-application.8ccfc8a69cb5.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/discord-bot-name-application.8ccfc8a69cb5.png&quot; width=&quot;3024&quot; height=&quot;1771&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-name-application.8ccfc8a69cb5.png&amp;amp;w=756&amp;amp;sig=663b4e94bcf90cb6c34d416805e4a488dfea3a36 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-name-application.8ccfc8a69cb5.png&amp;amp;w=1512&amp;amp;sig=46630dceba46441199dfd02f62565bc7be1ca896 1512w, https://files.realpython.com/media/discord-bot-name-application.8ccfc8a69cb5.png 3024w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Naming an Application&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Congratulations! You made a Discord application. On the resulting screen, you can see information about your application:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-app-info.146a24d590a6.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/discord-bot-app-info.146a24d590a6.png&quot; width=&quot;3015&quot; height=&quot;1767&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-app-info.146a24d590a6.png&amp;amp;w=753&amp;amp;sig=08d7b87d0cdda73c1ce9f040123d5fbe6b3ecc76 753w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-app-info.146a24d590a6.png&amp;amp;w=1507&amp;amp;sig=8d9fdeb253e6d562be88406244262b8797e50525 1507w, https://files.realpython.com/media/discord-bot-app-info.146a24d590a6.png 3015w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Application General Information&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Keep in mind that any program that interacts with Discord APIs requires a Discord application, not just bots. Bot-related APIs are only a subset of Discord&amp;rsquo;s total interface.&lt;/p&gt;
&lt;p&gt;However, since this tutorial is about how to make a Discord bot, navigate to the &lt;em&gt;Bot&lt;/em&gt; tab on the left-hand navigation list.&lt;/p&gt;
&lt;h3 id=&quot;creating-a-bot&quot;&gt;Creating a Bot&lt;/h3&gt;
&lt;p&gt;As you learned in the previous sections, a bot user is one that listens to and automatically reacts to certain events and commands on Discord.&lt;/p&gt;
&lt;p&gt;For your code to actually be manifested on Discord, you&amp;rsquo;ll need to create a bot user. To do so, select &lt;em&gt;Add Bot&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-add-bot.4735c88ff16b.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/discord-bot-add-bot.4735c88ff16b.png&quot; width=&quot;3021&quot; height=&quot;1761&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-add-bot.4735c88ff16b.png&amp;amp;w=755&amp;amp;sig=1bd131ee29f9c52aed1698d09c26f4267abb5f02 755w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-add-bot.4735c88ff16b.png&amp;amp;w=1510&amp;amp;sig=3b9afe030a68a934e1f3730ebab7c9bd7e8981cf 1510w, https://files.realpython.com/media/discord-bot-add-bot.4735c88ff16b.png 3021w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Add Bot&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once you confirm that you want to add the bot to your application, you&amp;rsquo;ll see the new bot user in the portal:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-created.fbdf4a021810.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/discord-bot-created.fbdf4a021810.png&quot; width=&quot;3009&quot; height=&quot;1760&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-created.fbdf4a021810.png&amp;amp;w=752&amp;amp;sig=8d9dc28ff753dff981137aef1b7e5add00a429a1 752w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-created.fbdf4a021810.png&amp;amp;w=1504&amp;amp;sig=2ec8e17f1a229eb212a96d7f85c9b680391776f1 1504w, https://files.realpython.com/media/discord-bot-created.fbdf4a021810.png 3009w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Bot Created Successfully&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice that, by default, your bot user will inherit the name of your application. Instead, update the username to something more bot-like, such as &lt;code&gt;RealPythonTutorialBot&lt;/code&gt;, and &lt;em&gt;Save Changes&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-rename-bot.008fd6ed6354.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/discord-bot-rename-bot.008fd6ed6354.png&quot; width=&quot;3023&quot; height=&quot;1770&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-rename-bot.008fd6ed6354.png&amp;amp;w=755&amp;amp;sig=39e7af71df9ef2095bce4d7e964973af010903c0 755w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-rename-bot.008fd6ed6354.png&amp;amp;w=1511&amp;amp;sig=252ca9f5542ba888771dd8aa32cf36b65cbc6317 1511w, https://files.realpython.com/media/discord-bot-rename-bot.008fd6ed6354.png 3023w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Rename Bot&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, the bot&amp;rsquo;s all set and ready to go, but to where?&lt;/p&gt;
&lt;p&gt;A bot user is not useful if it&amp;rsquo;s not interacting with other users. Next, you&amp;rsquo;ll create a guild so that your bot can interact with other users.&lt;/p&gt;
&lt;h3 id=&quot;creating-a-guild&quot;&gt;Creating a Guild&lt;/h3&gt;
&lt;p&gt;A &lt;strong&gt;guild&lt;/strong&gt; (or a &lt;strong&gt;server&lt;/strong&gt;, as it is often called in Discord&amp;rsquo;s user interface) is a specific group of channels where users congregate to chat.&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; While &lt;strong&gt;guild&lt;/strong&gt; and &lt;strong&gt;server&lt;/strong&gt; are interchangeable, this article will use the term &lt;strong&gt;guild&lt;/strong&gt; primarily because the APIs stick to the same term. The term &lt;strong&gt;server&lt;/strong&gt; will only be used when referring to a guild in the graphical UI.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For example, say you want to create a space where users can come together and talk about your latest game. You&amp;rsquo;d start by creating a guild. Then, in your guild, you could have multiple channels, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;General Discussion:&lt;/strong&gt; A channel for users to talk about whatever they want&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spoilers, Beware:&lt;/strong&gt; A channel for users who have finished your game to talk about all the end game reveals&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Announcements:&lt;/strong&gt; A channel for you to announce game updates and for users to discuss them&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you&amp;rsquo;ve created your guild, you&amp;rsquo;d invite other users to populate it.&lt;/p&gt;
&lt;p&gt;So, to create a guild, head to your Discord &lt;a href=&quot;https://discordapp.com/channels/@me&quot;&gt;home&lt;/a&gt; page:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-homepage.f533b989cedd.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/discord-bot-homepage.f533b989cedd.png&quot; width=&quot;3028&quot; height=&quot;1717&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-homepage.f533b989cedd.png&amp;amp;w=757&amp;amp;sig=34788068aad51ef7668a3e5ff0583199519ec3c9 757w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-homepage.f533b989cedd.png&amp;amp;w=1514&amp;amp;sig=e36d4b45395b91c00d546eee352c80cee2f8165a 1514w, https://files.realpython.com/media/discord-bot-homepage.f533b989cedd.png 3028w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: User Account Home Page&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From this home page, you can view and add friends, direct messages, and guilds. From here, select the &lt;em&gt;+&lt;/em&gt; icon on the left-hand side of the web page to &lt;em&gt;Add a Server&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-add-server.bd5a5a58c50c.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/discord-bot-add-server.bd5a5a58c50c.png&quot; width=&quot;3027&quot; height=&quot;1721&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-add-server.bd5a5a58c50c.png&amp;amp;w=756&amp;amp;sig=1113434567a2bedb5b26726cce843adc7e5791d6 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-add-server.bd5a5a58c50c.png&amp;amp;w=1513&amp;amp;sig=5cb289f097eac68358ee2400d26e45ee9e377fd6 1513w, https://files.realpython.com/media/discord-bot-add-server.bd5a5a58c50c.png 3027w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Add Server&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This will present two options, &lt;em&gt;Create a server&lt;/em&gt; and &lt;em&gt;Join a Server&lt;/em&gt;. In this case, select &lt;em&gt;Create a server&lt;/em&gt; and enter a name for your guild:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-create-server.922dba753792.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/discord-bot-create-server.922dba753792.png&quot; width=&quot;3023&quot; height=&quot;1716&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-create-server.922dba753792.png&amp;amp;w=755&amp;amp;sig=e5083d753497fc156dfec6c3b351abd790b8c0d8 755w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-create-server.922dba753792.png&amp;amp;w=1511&amp;amp;sig=4709fdcaa3feede390c444431adbb70f998f3f04 1511w, https://files.realpython.com/media/discord-bot-create-server.922dba753792.png 3023w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Naming a Server&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve finished creating your guild, you&amp;rsquo;ll be able to see the users on the right-hand side and the channels on the left:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-server.cba61f3781cf.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/discord-bot-server.cba61f3781cf.png&quot; width=&quot;3026&quot; height=&quot;1721&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-server.cba61f3781cf.png&amp;amp;w=756&amp;amp;sig=b8d05142625b9e2ce814747d1cf64921eba8e048 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-server.cba61f3781cf.png&amp;amp;w=1513&amp;amp;sig=6b6139eeecc4f1f64523d0a4d96f69e1a623c558 1513w, https://files.realpython.com/media/discord-bot-server.cba61f3781cf.png 3026w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Newly Created Server&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The final step on Discord is to register your bot with your new guild.&lt;/p&gt;
&lt;h3 id=&quot;adding-a-bot-to-a-guild&quot;&gt;Adding a Bot to a Guild&lt;/h3&gt;
&lt;p&gt;A bot can&amp;rsquo;t accept invites like a normal user can. Instead, you&amp;rsquo;ll add your bot using the OAuth2 protocol.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical Detail:&lt;/strong&gt; &lt;a href=&quot;https://oauth.net/2/&quot;&gt;OAuth2&lt;/a&gt; is a protocol for dealing with authorization, where a service can grant a client application limited access based on the application&amp;rsquo;s credentials and allowed scopes.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To do so, head back to the &lt;a href=&quot;http://discordapp.com/developers/applications&quot;&gt;Developer Portal&lt;/a&gt; and select the OAuth2 page from the left-hand navigation:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-oauth2.7c000bfe571b.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/discord-bot-oauth2.7c000bfe571b.png&quot; width=&quot;3008&quot; height=&quot;1770&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-oauth2.7c000bfe571b.png&amp;amp;w=752&amp;amp;sig=a7d51e04cbb851359c7fe643d80acb8e1674d8a2 752w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-oauth2.7c000bfe571b.png&amp;amp;w=1504&amp;amp;sig=5ba25b1a754b3d08bb200328f56ea71e8b71db81 1504w, https://files.realpython.com/media/discord-bot-oauth2.7c000bfe571b.png 3008w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Application OAuth2&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From this window, you&amp;rsquo;ll see the OAuth2 URL Generator.&lt;/p&gt;
&lt;p&gt;This tool generates an authorization URL that hits Discord&amp;rsquo;s OAuth2 API and authorizes API access using your application&amp;rsquo;s credentials.&lt;/p&gt;
&lt;p&gt;In this case, you&amp;rsquo;ll want to grant your application&amp;rsquo;s bot user access to Discord APIs using your application&amp;rsquo;s OAuth2 credentials.&lt;/p&gt;
&lt;p&gt;To do this, scroll down and select &lt;em&gt;bot&lt;/em&gt; from the &lt;em&gt;SCOPES&lt;/em&gt; options and &lt;em&gt;Administrator&lt;/em&gt; from &lt;em&gt;BOT PERMISSIONS&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-scopes.ee333b7a5987.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/discord-bot-scopes.ee333b7a5987.png&quot; width=&quot;3012&quot; height=&quot;1766&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-scopes.ee333b7a5987.png&amp;amp;w=753&amp;amp;sig=3df33d0353cab7ddbf213779e83c711e5d629e21 753w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-scopes.ee333b7a5987.png&amp;amp;w=1506&amp;amp;sig=259c0a008e687ca6bcb131a63d825e4a3f5133c5 1506w, https://files.realpython.com/media/discord-bot-scopes.ee333b7a5987.png 3012w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Application Scopes and Bot Permissions&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, Discord has generated your application&amp;rsquo;s authorization URL with the selected scope and permissions.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; While we&amp;rsquo;re using &lt;em&gt;Administrator&lt;/em&gt; for the purposes of this tutorial, you should be as granular as possible when granting permissions in a real-world application.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Select &lt;em&gt;Copy&lt;/em&gt; beside the URL that was generated for you, paste it into your browser, and select your guild from the dropdown options:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-select-server.3cd1af626256.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/discord-bot-select-server.3cd1af626256.png&quot; width=&quot;3023&quot; height=&quot;1715&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-select-server.3cd1af626256.png&amp;amp;w=755&amp;amp;sig=bfa0dba079ebee97013871c01220f66505eed020 755w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-select-server.3cd1af626256.png&amp;amp;w=1511&amp;amp;sig=f2e91e59e77705a053b9930c27d1bf198ff6c7dc 1511w, https://files.realpython.com/media/discord-bot-select-server.3cd1af626256.png 3023w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Add Bot to a Server&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click &lt;em&gt;Authorize&lt;/em&gt;, and you&amp;rsquo;re done!&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 might get a &lt;a href=&quot;https://en.wikipedia.org/wiki/ReCAPTCHA&quot;&gt;reCAPTCHA&lt;/a&gt; before moving on. If so, you&amp;rsquo;ll need to prove you&amp;rsquo;re a human.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you go back to your guild, then you&amp;rsquo;ll see that the bot has been added:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-added-to-guild.4a6b4477bc1e.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/discord-bot-added-to-guild.4a6b4477bc1e.png&quot; width=&quot;3024&quot; height=&quot;1719&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-added-to-guild.4a6b4477bc1e.png&amp;amp;w=756&amp;amp;sig=39634e4118660e59511dee28f86e7bb290192f3d 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-added-to-guild.4a6b4477bc1e.png&amp;amp;w=1512&amp;amp;sig=add9851baae9338210082db661a6277cad86ef5f 1512w, https://files.realpython.com/media/discord-bot-added-to-guild.4a6b4477bc1e.png 3024w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Bot Added to Guild&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In summary, you&amp;rsquo;ve created:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;application&lt;/strong&gt; that your bot will use to authenticate with Discord&amp;rsquo;s APIs&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;bot&lt;/strong&gt; user that you&amp;rsquo;ll use to interact with other users and events in your guild&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;guild&lt;/strong&gt; in which your user account and your bot user will be active&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Discord&lt;/strong&gt; account with which you created everything else and that you&amp;rsquo;ll use to interact with your bot&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, you know how to make a Discord bot using the Developer Portal. Next comes the fun stuff: implementing your bot in Python!&lt;/p&gt;
&lt;h2 id=&quot;how-to-make-a-discord-bot-in-python&quot;&gt;How to Make a Discord Bot in Python&lt;/h2&gt;
&lt;p&gt;Since you&amp;rsquo;re learning how to make a Discord bot with Python, you&amp;rsquo;ll be using &lt;code&gt;discord.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://discordpy.readthedocs.io/en/latest/index.html&quot;&gt;&lt;code&gt;discord.py&lt;/code&gt;&lt;/a&gt; is a Python library that exhaustively implements Discord&amp;rsquo;s APIs in an efficient and Pythonic way. This includes utilizing Python&amp;rsquo;s implementation of &lt;a href=&quot;https://realpython.com/async-io-python/&quot;&gt;Async IO&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Begin by installing &lt;code&gt;discord.py&lt;/code&gt; 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 -U discord.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that you&amp;rsquo;ve installed &lt;code&gt;discord.py&lt;/code&gt;, you&amp;rsquo;ll use it to create your first connection to Discord!&lt;/p&gt;
&lt;h2 id=&quot;creating-a-discord-connection&quot;&gt;Creating a Discord Connection&lt;/h2&gt;
&lt;p&gt;The first step in implementing your bot user is to create a connection to Discord. With &lt;code&gt;discord.py&lt;/code&gt;, you do this by creating an instance of &lt;code&gt;Client&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&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;{client.user}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; has connected to Discord!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A &lt;code&gt;Client&lt;/code&gt; is an object that represents a connection to Discord. A &lt;code&gt;Client&lt;/code&gt; handles events, tracks state, and generally interacts with Discord APIs.&lt;/p&gt;
&lt;p&gt;Here, you&amp;rsquo;ve created a &lt;code&gt;Client&lt;/code&gt; and implemented its &lt;code&gt;on_ready()&lt;/code&gt; event handler, which handles the event when the &lt;code&gt;Client&lt;/code&gt; has established a connection to Discord and it has finished preparing the data that Discord has sent, such as login state, guild and channel data, and more.&lt;/p&gt;
&lt;p&gt;In other words, &lt;code&gt;on_ready()&lt;/code&gt; will be called (and your message will be printed) once &lt;code&gt;client&lt;/code&gt; is ready for further action. You&amp;rsquo;ll learn more about event handlers later in this article.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re working with secrets such as your Discord token, it&amp;rsquo;s good practice to read it into your program from an environment variable. Using environment variables helps you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid putting the secrets into source control&lt;/li&gt;
&lt;li&gt;Use different variables for development and production environments without changing your code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While you could &lt;code&gt;export DISCORD_TOKEN={your-bot-token}&lt;/code&gt;, an easier solution is to save a &lt;code&gt;.env&lt;/code&gt; file on all machines that will be running this code. This is not only easier, since you won&amp;rsquo;t have to &lt;code&gt;export&lt;/code&gt; your token every time you clear your shell, but it also protects you from storing your secrets in your shell&amp;rsquo;s history.&lt;/p&gt;
&lt;p&gt;Create a file named &lt;code&gt;.env&lt;/code&gt; in the same directory as &lt;code&gt;bot.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# .env
DISCORD_TOKEN={your-bot-token}
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll need to replace &lt;code&gt;{your-bot-token}&lt;/code&gt; with your bot&amp;rsquo;s token, which you can get by going back to the &lt;em&gt;Bot&lt;/em&gt; page on the &lt;a href=&quot;http://discordapp.com/developers/applications&quot;&gt;Developer Portal&lt;/a&gt; and clicking &lt;em&gt;Copy&lt;/em&gt; under the &lt;em&gt;TOKEN&lt;/em&gt; section:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-copy-token.1228e6cb6cba.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/discord-bot-copy-token.1228e6cb6cba.png&quot; width=&quot;3024&quot; height=&quot;1767&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-copy-token.1228e6cb6cba.png&amp;amp;w=756&amp;amp;sig=57425662c2056deac50ebeb9a8d2891d4a8a6b53 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-copy-token.1228e6cb6cba.png&amp;amp;w=1512&amp;amp;sig=c8c437a86a1fb23a94e35050f5c969f5f20c4814 1512w, https://files.realpython.com/media/discord-bot-copy-token.1228e6cb6cba.png 3024w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Copy Bot Token&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Looking back at the &lt;code&gt;bot.py&lt;/code&gt; code, you&amp;rsquo;ll notice a library called &lt;a href=&quot;https://github.com/theskumar/python-dotenv&quot;&gt;&lt;code&gt;dotenv&lt;/code&gt;&lt;/a&gt;. This library is handy for working with &lt;code&gt;.env&lt;/code&gt; files. &lt;code&gt;load_dotenv()&lt;/code&gt; loads environment variables from a &lt;code&gt;.env&lt;/code&gt; file into your shell&amp;rsquo;s environment variables so that you can use them in your code.&lt;/p&gt;
&lt;p&gt;Install &lt;code&gt;dotenv&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 -U python-dotenv
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, &lt;code&gt;client.run()&lt;/code&gt; runs your &lt;code&gt;Client&lt;/code&gt; using your bot&amp;rsquo;s token.&lt;/p&gt;
&lt;p&gt;Now that you&amp;rsquo;ve set up both &lt;code&gt;bot.py&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt;, you can run your code:&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 bot.py
&lt;span class=&quot;go&quot;&gt;RealPythonTutorialBot#9643 has connected to Discord!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Great! Your &lt;code&gt;Client&lt;/code&gt; has connected to Discord using your bot&amp;rsquo;s token. In the next section, you&amp;rsquo;ll build on this &lt;code&gt;Client&lt;/code&gt; by interacting with more Discord APIs.&lt;/p&gt;
&lt;h2 id=&quot;interacting-with-discord-apis&quot;&gt;Interacting With Discord APIs&lt;/h2&gt;
&lt;p&gt;Using a &lt;code&gt;Client&lt;/code&gt;, you have access to a wide range of Discord APIs.&lt;/p&gt;
&lt;p&gt;For example, let&amp;rsquo;s say you wanted to write the name and identifier of the guild that you registered your bot user with to the console.&lt;/p&gt;
&lt;p&gt;First, you&amp;rsquo;ll need to add a new environment variable:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# .env
DISCORD_TOKEN={your-bot-token}
&lt;span class=&quot;hll&quot;&gt;DISCORD_GUILD={your-guild-name}
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Don&amp;rsquo;t forget that you&amp;rsquo;ll need to replace the two placeholders with actual values:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;{your-bot-token}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{your-guild-name}&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Remember that Discord calls &lt;code&gt;on_ready()&lt;/code&gt;, which you used before, once the &lt;code&gt;Client&lt;/code&gt; has made the connection and prepared the data. So, you can rely on the guild data being available inside &lt;code&gt;on_ready()&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;GUILD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_GUILD&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&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;guild&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guilds&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;guild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GUILD&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;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;{client.user}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; is connected to the following guild:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
        &lt;span class=&quot;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;{guild.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;(id: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{guild.id}&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;n&quot;&gt;client&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;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you looped through the guild data that Discord has sent &lt;code&gt;client&lt;/code&gt;, namely &lt;code&gt;client.guilds&lt;/code&gt;. Then, you found the guild with the matching name and printed a &lt;a href=&quot;https://realpython.com/python-f-strings/&quot;&gt;formatted string&lt;/a&gt; to &lt;code&gt;stdout&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; Even though you can be pretty confident at this point in the tutorial that your bot is only connected to a single guild (so &lt;code&gt;client.guilds[0]&lt;/code&gt; would be simpler), it&amp;rsquo;s important to realize that a bot user can be connected to many guilds.&lt;/p&gt;
&lt;p&gt;Therefore, a more robust solution is to loop through &lt;code&gt;client.guilds&lt;/code&gt; to find the one you&amp;rsquo;re looking for.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Run the program to see the results:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python bot.py
&lt;span class=&quot;go&quot;&gt;RealPythonTutorialBot#9643 is connected to the following guild:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;RealPythonTutorialServer(id: 571759877328732195)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Great! You can see the name of your bot, the name of your server, and the server&amp;rsquo;s identification number.&lt;/p&gt;
&lt;p&gt;Another interesting bit of data you can pull from a guild is the list of users who are members of the guild:&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;GUILD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_GUILD&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&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;guild&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guilds&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;guild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GUILD&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;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;{client.user}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; is connected to the following guild:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
        &lt;span class=&quot;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;{guild.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;(id: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{guild.id}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;members&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; - &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;members&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;Guild Members:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; - &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{members}&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;n&quot;&gt;client&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;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By looping through &lt;code&gt;guild.members&lt;/code&gt;, you pulled the names of all of the members of the guild and printed them with a formatted string.&lt;/p&gt;
&lt;p&gt;When you run the program, you should see at least the name of the account you created the guild with and the name of the bot user itself:&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 bot.py
&lt;span class=&quot;go&quot;&gt;RealPythonTutorialBot#9643 is connected to the following guild:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;RealPythonTutorialServer(id: 571759877328732195)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Guild Members:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; - aronq2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; - RealPythonTutorialBot&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These examples barely scratch the surface of the APIs available on Discord, be sure to check out their &lt;a href=&quot;https://discordpy.readthedocs.io/en/latest/api.html#&quot;&gt;documentation&lt;/a&gt; to see all that they have to offer.&lt;/p&gt;
&lt;p&gt;Next, you&amp;rsquo;ll learn about some utility functions and how they can simplify these examples.&lt;/p&gt;
&lt;h2 id=&quot;using-utility-functions&quot;&gt;Using Utility Functions&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s take another look at the example from the last section where you printed the name and identifier of the bot&amp;rsquo;s guild:&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;GUILD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_GUILD&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&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;guild&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guilds&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;guild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GUILD&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;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;{client.user}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; is connected to the following guild:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
        &lt;span class=&quot;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;{guild.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;(id: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{guild.id}&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;n&quot;&gt;client&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;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You could clean up this code by using some of the utility functions available in &lt;code&gt;discord.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://discordpy.readthedocs.io/en/latest/api.html#discord.utils.find&quot;&gt;&lt;code&gt;discord.utils.find()&lt;/code&gt;&lt;/a&gt; is one utility that can improve the simplicity and readability of this code by replacing the &lt;code&gt;for&lt;/code&gt; loop with an intuitive, abstracted 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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;GUILD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_GUILD&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;guild&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&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;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GUILD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guilds&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;{client.user}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; is connected to the following guild:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
        &lt;span class=&quot;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;{guild.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;(id: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{guild.id}&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;n&quot;&gt;client&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;TOKEN&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;find()&lt;/code&gt; takes a function, called a &lt;strong&gt;predicate&lt;/strong&gt;, which identifies some characteristic of the element in the iterable that you&amp;rsquo;re looking for. Here, you used a particular type of anonymous function, called a &lt;a href=&quot;https://realpython.com/python-lambda/&quot;&gt;lambda&lt;/a&gt;, as the predicate.&lt;/p&gt;
&lt;p&gt;In this case, you&amp;rsquo;re trying to find the guild with the same name as the one you stored in the &lt;code&gt;DISCORD_GUILD&lt;/code&gt; environment variable. Once &lt;code&gt;find()&lt;/code&gt; locates an element in the iterable that satisfies the predicate, it will return the element. This is essentially equivalent to the &lt;code&gt;break&lt;/code&gt; statement in the previous example, but cleaner.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;discord.py&lt;/code&gt; has even abstracted this concept one step further with the &lt;a href=&quot;https://discordpy.readthedocs.io/en/latest/api.html#discord.utils.get&quot;&gt;&lt;code&gt;get()&lt;/code&gt; utility&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;c1&quot;&gt;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;GUILD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_GUILD&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;guild&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guilds&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;n&quot;&gt;GUILD&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;{client.user}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; is connected to the following guild:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
        &lt;span class=&quot;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;{guild.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;(id: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{guild.id}&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;n&quot;&gt;client&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;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;get()&lt;/code&gt; takes the iterable and some keyword arguments. The keyword arguments represent attributes of the elements in the iterable that must all be satisfied for &lt;code&gt;get()&lt;/code&gt; to return the element.&lt;/p&gt;
&lt;p&gt;In this example, you&amp;rsquo;ve identified &lt;code&gt;name=GUILD&lt;/code&gt; as the attribute that must be satisfied.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical Detail:&lt;/strong&gt; Under the hood, &lt;code&gt;get()&lt;/code&gt; actually uses the &lt;code&gt;attrs&lt;/code&gt; keyword arguments to build a predicate, which it then uses to call &lt;code&gt;find()&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now that you&amp;rsquo;ve learned the basics of interacting with APIs, you&amp;rsquo;ll dive a little deeper into the function that you&amp;rsquo;ve been using to access them: &lt;code&gt;on_ready()&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;responding-to-events&quot;&gt;Responding to Events&lt;/h2&gt;
&lt;p&gt;You already learned that &lt;code&gt;on_ready()&lt;/code&gt; is an event. In fact, you might have noticed that it is identified as such in the code by the &lt;code&gt;client.event&lt;/code&gt; &lt;a href=&quot;https://realpython.com/primer-on-python-decorators/&quot;&gt;decorator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But what is an event?&lt;/p&gt;
&lt;p&gt;An &lt;strong&gt;event&lt;/strong&gt; is something that happens on Discord that you can use to trigger a reaction in your code. Your code will listen for and then respond to events.&lt;/p&gt;
&lt;p&gt;Using the example you&amp;rsquo;ve seen already, the &lt;code&gt;on_ready()&lt;/code&gt; event handler handles the event that the &lt;code&gt;Client&lt;/code&gt; has made a connection to Discord and prepared its response data.&lt;/p&gt;
&lt;p&gt;So, when Discord fires an event, &lt;code&gt;discord.py&lt;/code&gt; will route the event data to the corresponding event handler on your connected &lt;code&gt;Client&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are two ways in &lt;code&gt;discord.py&lt;/code&gt; to implement an event handler:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using the &lt;code&gt;client.event&lt;/code&gt; decorator&lt;/li&gt;
&lt;li&gt;Creating a subclass of &lt;code&gt;Client&lt;/code&gt; and overriding its handler methods&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You already saw the implementation using the decorator. Next, take a look at how to subclass &lt;code&gt;Client&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&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;CustomClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&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;on_ready&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;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;{self.user}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; has connected to Discord!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CustomClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, just like before, you&amp;rsquo;ve created a &lt;code&gt;client&lt;/code&gt; variable and called &lt;code&gt;.run()&lt;/code&gt; with your Discord token. The actual &lt;code&gt;Client&lt;/code&gt; is different, however. Instead of using the normal base class, &lt;code&gt;client&lt;/code&gt; is an instance of &lt;code&gt;CustomClient&lt;/code&gt;, which has an overridden &lt;code&gt;on_ready()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;There is no difference between the two implementation styles of events, but this tutorial will primarily use the decorator version because it looks similar to how you implement &lt;code&gt;Bot&lt;/code&gt; commands, which is a topic you&amp;rsquo;ll cover in a bit.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical Detail:&lt;/strong&gt; Regardless of how you implement your event handler, one thing must be consistent: all event handlers in &lt;code&gt;discord.py&lt;/code&gt; must be &lt;a href=&quot;https://realpython.com/async-io-python/#the-asyncawait-syntax-and-native-coroutines&quot;&gt;coroutines&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now that you&amp;rsquo;ve learned how to create an event handler, let&amp;rsquo;s walk through some different examples of handlers you can create.&lt;/p&gt;
&lt;h3 id=&quot;welcoming-new-members&quot;&gt;Welcoming New Members&lt;/h3&gt;
&lt;p&gt;Previously, you saw the example of responding to the event where a member joins a guild. In that example, your bot user could send them a message, welcoming them to your Discord community.&lt;/p&gt;
&lt;p&gt;Now, you&amp;rsquo;ll implement that behavior in your &lt;code&gt;Client&lt;/code&gt;, using event handlers, and verify its behavior in Discord:&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&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;{client.user.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; has connected to Discord!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_member_join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_dm&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;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dm_channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&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;Hi &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{member.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;, welcome to my Discord server!&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Like before, you handled the &lt;code&gt;on_ready()&lt;/code&gt; event by printing the bot user&amp;rsquo;s name in a formatted string. New, however, is the implementation of the &lt;code&gt;on_member_join()&lt;/code&gt; event handler.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;on_member_join()&lt;/code&gt;, as its name suggests, handles the event of a new member joining a guild.&lt;/p&gt;
&lt;p&gt;In this example, you used &lt;code&gt;member.create_dm()&lt;/code&gt; to create a direct message channel. Then, you used that channel to &lt;code&gt;.send()&lt;/code&gt; a direct message to that new member.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical Detail:&lt;/strong&gt; Notice the &lt;code&gt;await&lt;/code&gt; keyword before &lt;code&gt;member.create_dm()&lt;/code&gt; and &lt;code&gt;member.dm_channel.send()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;await&lt;/code&gt; suspends the execution of the surrounding coroutine until the execution of each coroutine has finished.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now, let&amp;rsquo;s test out your bot&amp;rsquo;s new behavior.&lt;/p&gt;
&lt;p&gt;First, run your new version of &lt;code&gt;bot.py&lt;/code&gt; and wait for the &lt;code&gt;on_ready()&lt;/code&gt; event to fire, logging your message 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;gp&quot;&gt;$&lt;/span&gt; python bot.py
&lt;span class=&quot;go&quot;&gt;RealPythonTutorialBot has connected to Discord!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, head over to &lt;a href=&quot;https://discordapp.com/&quot;&gt;Discord&lt;/a&gt;, log in, and navigate to your guild by selecting it from the left-hand side of the screen:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-navigate-to-server.dfef0364630f.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/discord-bot-navigate-to-server.dfef0364630f.png&quot; width=&quot;3024&quot; height=&quot;1767&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-navigate-to-server.dfef0364630f.png&amp;amp;w=756&amp;amp;sig=e385f92a8203695f50bbd2d55922fc8ae3b4599e 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-navigate-to-server.dfef0364630f.png&amp;amp;w=1512&amp;amp;sig=7b1fd07e2bfbee2e23b36aa922a614d938b29698 1512w, https://files.realpython.com/media/discord-bot-navigate-to-server.dfef0364630f.png 3024w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Navigate to Server&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Select &lt;em&gt;Invite People&lt;/em&gt; just beside the guild list where you selected your guild. Check the box that says &lt;em&gt;Set this link to never expire&lt;/em&gt; and copy the link:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-copy-invite.0dd6b229c819.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/discord-bot-copy-invite.0dd6b229c819.png&quot; width=&quot;3024&quot; height=&quot;1766&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-copy-invite.0dd6b229c819.png&amp;amp;w=756&amp;amp;sig=81a88bffad8cbfa324a0eef38a1b6ff7ccfc67a5 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-copy-invite.0dd6b229c819.png&amp;amp;w=1512&amp;amp;sig=3c9f1911a3ebeb646c31e570e6a9ca8cff23f8cd 1512w, https://files.realpython.com/media/discord-bot-copy-invite.0dd6b229c819.png 3024w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Copy Invite Link&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, with the invite link copied, create a new account and join the guild using your invite link:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-accept-invite.4b33a1ba7062.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/discord-bot-accept-invite.4b33a1ba7062.png&quot; width=&quot;3021&quot; height=&quot;1767&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-accept-invite.4b33a1ba7062.png&amp;amp;w=755&amp;amp;sig=3b1a1db4101d859112e0a1d224d2aa8cc7606715 755w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-accept-invite.4b33a1ba7062.png&amp;amp;w=1510&amp;amp;sig=c5efa82e1d5940ff89422813371ddc83054cdbce 1510w, https://files.realpython.com/media/discord-bot-accept-invite.4b33a1ba7062.png 3021w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Accept Invite&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;First, you&amp;rsquo;ll see that Discord introduced you to the guild by default with an automated message. More importantly though, notice the badge on the left-hand side of the screen that notifies you of a new message:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-direct-message-notification.95e423f72678.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/discord-bot-direct-message-notification.95e423f72678.png&quot; width=&quot;3022&quot; height=&quot;1768&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-direct-message-notification.95e423f72678.png&amp;amp;w=755&amp;amp;sig=84f08a7484e333f40081aa4071dafc4d331ca7f2 755w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-direct-message-notification.95e423f72678.png&amp;amp;w=1511&amp;amp;sig=51ed613c1cbe18a474ca12e6b648cb18d9a0505a 1511w, https://files.realpython.com/media/discord-bot-direct-message-notification.95e423f72678.png 3022w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Direct Message Notification&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you select it, you&amp;rsquo;ll see a private message from your bot user:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-direct-message.7f49832b7bb7.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/discord-bot-direct-message.7f49832b7bb7.png&quot; width=&quot;3024&quot; height=&quot;1769&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-direct-message.7f49832b7bb7.png&amp;amp;w=756&amp;amp;sig=70663b008b61bdb83ce3f2f3b6cc4d4abda8a914 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-direct-message.7f49832b7bb7.png&amp;amp;w=1512&amp;amp;sig=5874eab3fb67f6bd0ba0b3a4ed5c6d401e23f8c8 1512w, https://files.realpython.com/media/discord-bot-direct-message.7f49832b7bb7.png 3024w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Direct Message&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Perfect! Your bot user is now interacting with other users with minimal code.&lt;/p&gt;
&lt;p&gt;Next, you&amp;rsquo;ll learn how to respond to specific user messages in the chat.&lt;/p&gt;
&lt;h3 id=&quot;responding-to-messages&quot;&gt;Responding to Messages&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s add on to the previous functionality of your bot by handling the &lt;code&gt;on_message()&lt;/code&gt; event.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;on_message()&lt;/code&gt; occurs when a message is posted in a channel that your bot has access to. In this example, you&amp;rsquo;ll respond to the message &lt;code&gt;&#39;99!&#39;&lt;/code&gt; with a one-liner from the television show &lt;a href=&quot;https://www.nbc.com/brooklyn-nine-nine&quot;&gt;Brooklyn Nine-Nine&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;nd&quot;&gt;@client&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;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;on_message&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;brooklyn_99_quotes&lt;/span&gt; &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;I&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;m the human form of the 💯 emoji.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;Bingpot!&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;s1&quot;&gt;&amp;#39;Cool. Cool cool cool cool cool cool cool, &amp;#39;&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;no doubt no doubt no doubt no doubt.&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;99!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&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;brooklyn_99_quotes&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;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The bulk of this event handler looks at the &lt;code&gt;message.content&lt;/code&gt;, checks to see if it&amp;rsquo;s equal to &lt;code&gt;&#39;99!&#39;&lt;/code&gt;, and responds by sending a random quote to the message&amp;rsquo;s channel if it is.&lt;/p&gt;
&lt;p&gt;The other piece is an important one:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because a &lt;code&gt;Client&lt;/code&gt; can&amp;rsquo;t tell the difference between a bot user and a normal user account, your &lt;code&gt;on_message()&lt;/code&gt; handler should protect against a potentially recursive case where the bot sends a message that it might, itself, handle.&lt;/p&gt;
&lt;p&gt;To illustrate, let&amp;rsquo;s say you want your bot to listen for users telling each other &lt;code&gt;&#39;Happy Birthday&#39;&lt;/code&gt;. You could implement your &lt;code&gt;on_message()&lt;/code&gt; handler 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;nd&quot;&gt;@client&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;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;on_message&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;happy birthday&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Happy Birthday! 🎈🎉&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aside from the potentially spammy nature of this event handler, it also has a devastating side effect. The message that the bot responds with contains the same message it&amp;rsquo;s going to handle!&lt;/p&gt;
&lt;p&gt;So, if one person in the channel tells another &amp;ldquo;Happy Birthday,&amp;rdquo; then the bot will also chime in&amp;hellip; again&amp;hellip; and again&amp;hellip; and again:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-happy-birthday-repetition.864acfe23979.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/discord-bot-happy-birthday-repetition.864acfe23979.png&quot; width=&quot;3028&quot; height=&quot;1769&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-happy-birthday-repetition.864acfe23979.png&amp;amp;w=757&amp;amp;sig=1e56e02abfd0366024a7df56f2111fbb023f42be 757w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-happy-birthday-repetition.864acfe23979.png&amp;amp;w=1514&amp;amp;sig=2f67cb61941a012ff7d260910406a5c427c8f4c4 1514w, https://files.realpython.com/media/discord-bot-happy-birthday-repetition.864acfe23979.png 3028w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Happy Birthday Message Repetition&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why it&amp;rsquo;s important to compare the &lt;code&gt;message.author&lt;/code&gt; to the &lt;code&gt;client.user&lt;/code&gt; (your bot user), and ignore any of its own messages.&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s fix &lt;code&gt;bot.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&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;{client.user.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; has connected to Discord!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_member_join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_dm&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;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dm_channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&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;Hi &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{member.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;, welcome to my Discord server!&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_message&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;brooklyn_99_quotes&lt;/span&gt; &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;I&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;m the human form of the 💯 emoji.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;Bingpot!&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;s1&quot;&gt;&amp;#39;Cool. Cool cool cool cool cool cool cool, &amp;#39;&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;no doubt no doubt no doubt no doubt.&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;99!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&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;brooklyn_99_quotes&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;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Don&amp;rsquo;t forget to &lt;code&gt;import random&lt;/code&gt; at the top of the module, since the &lt;code&gt;on_message()&lt;/code&gt; handler utilizes &lt;code&gt;random.choice()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Run the program:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python bot.py
&lt;span class=&quot;go&quot;&gt;RealPythonTutorialBot has connected to Discord!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, head over to Discord to test it out:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-brooklyn-99-quotes.e934592e025e.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/discord-bot-brooklyn-99-quotes.e934592e025e.png&quot; width=&quot;3027&quot; height=&quot;1767&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-brooklyn-99-quotes.e934592e025e.png&amp;amp;w=756&amp;amp;sig=4f9a47703207d0920393a69f3411bd7d5914521b 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-brooklyn-99-quotes.e934592e025e.png&amp;amp;w=1513&amp;amp;sig=d78013102c8901874e9632b66e4a8d1b26f7b7fc 1513w, https://files.realpython.com/media/discord-bot-brooklyn-99-quotes.e934592e025e.png 3027w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Quotes From Brooklyn Nine-Nine&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Great! Now that you&amp;rsquo;ve seen a few different ways to handle some common Discord events, you&amp;rsquo;ll learn how to deal with errors that event handlers may raise.&lt;/p&gt;
&lt;h3 id=&quot;handling-exceptions&quot;&gt;Handling Exceptions&lt;/h3&gt;
&lt;p&gt;As you&amp;rsquo;ve seen already, &lt;code&gt;discord.py&lt;/code&gt; is an event-driven system. This focus on events extends even to exceptions. When one event handler &lt;a href=&quot;https://realpython.com/python-exceptions/&quot;&gt;raises an &lt;code&gt;Exception&lt;/code&gt;&lt;/a&gt;, Discord calls &lt;code&gt;on_error()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The default behavior of &lt;code&gt;on_error()&lt;/code&gt; is to write the error message and stack trace to &lt;code&gt;stderr&lt;/code&gt;. To test this, add a special message handler to &lt;code&gt;on_message()&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_ready&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;{client.user.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; has connected to Discord!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_member_join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_dm&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;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dm_channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&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;Hi &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{member.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;, welcome to my Discord server!&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_message&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;brooklyn_99_quotes&lt;/span&gt; &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;I&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;m the human form of the 💯 emoji.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;Bingpot!&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;s1&quot;&gt;&amp;#39;Cool. Cool cool cool cool cool cool cool, &amp;#39;&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;no doubt no doubt no doubt no doubt.&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;99!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&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;brooklyn_99_quotes&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;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&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;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;raise-exception&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;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DiscordException&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The new &lt;code&gt;raise-exception&lt;/code&gt; message handler allows you to raise a &lt;code&gt;DiscordException&lt;/code&gt; on command.&lt;/p&gt;
&lt;p&gt;Run the program and type &lt;code&gt;raise-exception&lt;/code&gt; into the Discord channel:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-raise-exception.7fcae85fb06e.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/discord-bot-raise-exception.7fcae85fb06e.png&quot; width=&quot;3026&quot; height=&quot;1765&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-raise-exception.7fcae85fb06e.png&amp;amp;w=756&amp;amp;sig=5d0026bbd91a3b8bb1bd561f0779dde3150d588a 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-raise-exception.7fcae85fb06e.png&amp;amp;w=1513&amp;amp;sig=7b226812216c03ef139c4c33823dd6318dc34ec5 1513w, https://files.realpython.com/media/discord-bot-raise-exception.7fcae85fb06e.png 3026w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Raise Exception Message&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You should now see the &lt;code&gt;Exception&lt;/code&gt; that was raised by your &lt;code&gt;on_message()&lt;/code&gt; handler in the console:&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 bot.py
&lt;span class=&quot;go&quot;&gt;RealPythonTutorialBot has connected to Discord!&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Ignoring exception in on_message&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/client.py&amp;quot;, line 255, in _run_event&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    await coro(*args, **kwargs)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;bot.py&amp;quot;, line 42, in on_message&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    raise discord.DiscordException&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;discord.errors.DiscordException&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The exception was caught by the default error handler, so the output contains the message &lt;code&gt;Ignoring exception in on_message&lt;/code&gt;. Let&amp;rsquo;s fix that by handling that particular error. To do so, you&amp;rsquo;ll catch the &lt;code&gt;DiscordException&lt;/code&gt; and &lt;a href=&quot;https://realpython.com/working-with-files-in-python/&quot;&gt;write it to a file&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;on_error()&lt;/code&gt; event handler takes the &lt;code&gt;event&lt;/code&gt; as the first argument. In this case, we expect the &lt;code&gt;event&lt;/code&gt; to be &lt;code&gt;&#39;on_message&#39;&lt;/code&gt;. It also accepts &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; as flexible, positional and keyword arguments passed to the original event handler.&lt;/p&gt;
&lt;p&gt;So, since &lt;code&gt;on_message()&lt;/code&gt; takes a single argument, &lt;code&gt;message&lt;/code&gt;, we expect &lt;code&gt;args[0]&lt;/code&gt; to be the &lt;code&gt;message&lt;/code&gt; that the user sent in the Discord channel:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_error&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;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;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;err.log&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&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;s1&quot;&gt;&amp;#39;on_message&amp;#39;&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;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;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Unhandled message: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{args[0]}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the &lt;code&gt;Exception&lt;/code&gt; originated in the &lt;code&gt;on_message()&lt;/code&gt; event handler, you &lt;code&gt;.write()&lt;/code&gt; a formatted string to the file &lt;code&gt;err.log&lt;/code&gt;. If another event raises an &lt;code&gt;Exception&lt;/code&gt;, then we simply want our handler to re-raise the exception to invoke the default behavior.&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;bot.py&lt;/code&gt; and send the &lt;code&gt;raise-exception&lt;/code&gt; message again to view the output in &lt;code&gt;err.log&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; cat err.log
&lt;span class=&quot;go&quot;&gt;Unhandled message: &amp;lt;Message id=573845548923224084 pinned=False author=&amp;lt;Member id=543612676807327754 name=&amp;#39;alexronquillo&amp;#39; discriminator=&amp;#39;0933&amp;#39; bot=False nick=None guild=&amp;lt;Guild id=571759877328732195 name=&amp;#39;RealPythonTutorialServer&amp;#39; chunked=True&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of only a stack trace, you have a more informative error, showing the &lt;code&gt;message&lt;/code&gt; that caused &lt;code&gt;on_message()&lt;/code&gt; to raise the &lt;code&gt;DiscordException&lt;/code&gt;, saved to a file for longer persistence.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical Detail:&lt;/strong&gt; If you want to take the actual &lt;code&gt;Exception&lt;/code&gt; into account when you&amp;rsquo;re writing your error messages to &lt;code&gt;err.log&lt;/code&gt;, then you can use functions from &lt;code&gt;sys&lt;/code&gt;, such as &lt;a href=&quot;https://docs.python.org/library/sys.html#sys.exc_info&quot;&gt;&lt;code&gt;exc_info()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now that you have some experience handling different events and interacting with Discord APIs, you&amp;rsquo;ll learn about a subclass of &lt;code&gt;Client&lt;/code&gt; called &lt;code&gt;Bot&lt;/code&gt;, which implements some handy, bot-specific functionality.&lt;/p&gt;
&lt;h2 id=&quot;connecting-a-bot&quot;&gt;Connecting a Bot&lt;/h2&gt;
&lt;p&gt;A &lt;code&gt;Bot&lt;/code&gt; is a subclass of &lt;code&gt;Client&lt;/code&gt; that adds a little bit of extra functionality that is useful when you&amp;rsquo;re creating bot users. For example, a &lt;code&gt;Bot&lt;/code&gt; can handle events and commands, invoke validation checks, and more.&lt;/p&gt;
&lt;p&gt;Before you get into the features specific to &lt;code&gt;Bot&lt;/code&gt;, convert &lt;code&gt;bot.py&lt;/code&gt; to use a &lt;code&gt;Bot&lt;/code&gt; instead of a &lt;code&gt;Client&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 1&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord.ext&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command_prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@bot&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;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;on_ready&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;{bot.user.name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; has connected to Discord!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bot&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, &lt;code&gt;Bot&lt;/code&gt; can handle events the same way that &lt;code&gt;Client&lt;/code&gt; does. However, notice the differences between &lt;code&gt;Client&lt;/code&gt; and &lt;code&gt;Bot&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Bot&lt;/code&gt; is imported from the &lt;code&gt;discord.ext.commands&lt;/code&gt; module.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Bot&lt;/code&gt; initializer requires a &lt;code&gt;command_prefix&lt;/code&gt;, which you&amp;rsquo;ll learn more about in the next section.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The extensions library, &lt;code&gt;ext&lt;/code&gt;, offers several interesting components to help you create a Discord &lt;code&gt;Bot&lt;/code&gt;. One such component is the &lt;a href=&quot;https://discordpy.readthedocs.io/en/latest/ext/commands/commands.html&quot;&gt;&lt;code&gt;Command&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;using-bot-commands&quot;&gt;Using &lt;code&gt;Bot&lt;/code&gt; Commands&lt;/h3&gt;
&lt;p&gt;In general terms, a &lt;strong&gt;command&lt;/strong&gt; is an order that a user gives to a bot so that it will do something. Commands are different from events because they are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Arbitrarily defined&lt;/li&gt;
&lt;li&gt;Directly called by the user&lt;/li&gt;
&lt;li&gt;Flexible, in terms of their interface&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In technical terms, a &lt;strong&gt;&lt;code&gt;Command&lt;/code&gt;&lt;/strong&gt; is an object that wraps a function that is invoked by a text command in Discord. The text command must start with the &lt;code&gt;command_prefix&lt;/code&gt;, defined by the &lt;code&gt;Bot&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at an old event to better understand what this 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;c1&quot;&gt;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@client&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;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;on_message&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;brooklyn_99_quotes&lt;/span&gt; &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;I&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;m the human form of the 💯 emoji.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;Bingpot!&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;s1&quot;&gt;&amp;#39;Cool. Cool cool cool cool cool cool cool, &amp;#39;&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;no doubt no doubt no doubt no doubt.&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;99!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&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;brooklyn_99_quotes&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;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&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;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you created an &lt;code&gt;on_message()&lt;/code&gt; event handler, which receives the &lt;code&gt;message&lt;/code&gt; string and compares it to a pre-defined option: &lt;code&gt;&#39;99!&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Using a &lt;code&gt;Command&lt;/code&gt;, you can convert this example to be more specific:&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord.ext&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command_prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@bot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&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;s1&quot;&gt;&amp;#39;99&amp;#39;&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;nine_nine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;brooklyn_99_quotes&lt;/span&gt; &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;I&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;m the human form of the 💯 emoji.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;Bingpot!&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;s1&quot;&gt;&amp;#39;Cool. Cool cool cool cool cool cool cool, &amp;#39;&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;no doubt no doubt no doubt no doubt.&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;n&quot;&gt;response&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;brooklyn_99_quotes&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;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bot&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are several important characteristics to understand about using &lt;code&gt;Command&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Instead of using &lt;code&gt;bot.event&lt;/code&gt; like before, you use &lt;code&gt;bot.command()&lt;/code&gt;, passing the invocation command (&lt;code&gt;name&lt;/code&gt;) as its argument.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The function will now only be called when &lt;code&gt;!99&lt;/code&gt; is mentioned in chat. This is different than the &lt;code&gt;on_message()&lt;/code&gt; event, which was executed any time a user sent a message, regardless of the content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The command must be prefixed with the exclamation point (&lt;code&gt;!&lt;/code&gt; ) because that&amp;rsquo;s the &lt;code&gt;command_prefix&lt;/code&gt; that you defined in the initializer for your &lt;code&gt;Bot&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any &lt;code&gt;Command&lt;/code&gt; function (technically called a &lt;code&gt;callback&lt;/code&gt;) must accept at least one parameter, called &lt;code&gt;ctx&lt;/code&gt;, which is the &lt;a href=&quot;https://discordpy.readthedocs.io/en/latest/ext/commands/commands.html#invocation-context&quot;&gt;&lt;code&gt;Context&lt;/code&gt;&lt;/a&gt; surrounding the invoked &lt;code&gt;Command&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A &lt;code&gt;Context&lt;/code&gt; holds data such as the channel and guild that the user called the &lt;code&gt;Command&lt;/code&gt; from.&lt;/p&gt;
&lt;p&gt;Run the program:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python bot.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With your bot running, you can now head to Discord to try out your new command:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-brooklyn-99-command.f01b21540756.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/discord-bot-brooklyn-99-command.f01b21540756.png&quot; width=&quot;3031&quot; height=&quot;1769&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-brooklyn-99-command.f01b21540756.png&amp;amp;w=757&amp;amp;sig=dff1081b5b379d39c1cdd41115bdef90fa4a833c 757w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-brooklyn-99-command.f01b21540756.png&amp;amp;w=1515&amp;amp;sig=a05851348e0e7b2217a0900c531a16a42bf4f32e 1515w, https://files.realpython.com/media/discord-bot-brooklyn-99-command.f01b21540756.png 3031w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Brooklyn Nine-Nine Command&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From the user&amp;rsquo;s point of view, the practical difference is that the prefix helps formalize the command, rather than simply reacting to a particular &lt;code&gt;on_message()&lt;/code&gt; event.&lt;/p&gt;
&lt;p&gt;This comes with other great benefits as well. For example, you can invoke the &lt;code&gt;help&lt;/code&gt; command to see all the commands that your &lt;code&gt;Bot&lt;/code&gt; handles:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-help-command.a2ec772cc910.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/discord-bot-help-command.a2ec772cc910.png&quot; width=&quot;3027&quot; height=&quot;1767&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-help-command.a2ec772cc910.png&amp;amp;w=756&amp;amp;sig=122cba0d422a63e39e790208f553a16ebbceb674 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-help-command.a2ec772cc910.png&amp;amp;w=1513&amp;amp;sig=e8ef5a87dcca2de43f9ff198bb191746c5757465 1513w, https://files.realpython.com/media/discord-bot-help-command.a2ec772cc910.png 3027w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Help Command&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to add a description to your command so that the &lt;code&gt;help&lt;/code&gt; message is more informative, simply pass a &lt;code&gt;help&lt;/code&gt; description to the &lt;code&gt;.command()&lt;/code&gt; 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;c1&quot;&gt;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord.ext&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command_prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@bot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&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;s1&quot;&gt;&amp;#39;99&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Responds with a random quote from Brooklyn 99&amp;#39;&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;nine_nine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;brooklyn_99_quotes&lt;/span&gt; &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;I&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;m the human form of the 💯 emoji.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;Bingpot!&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;s1&quot;&gt;&amp;#39;Cool. Cool cool cool cool cool cool cool, &amp;#39;&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;no doubt no doubt no doubt no doubt.&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;n&quot;&gt;response&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;brooklyn_99_quotes&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;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bot&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, when the user invokes the &lt;code&gt;help&lt;/code&gt; command, your bot will present a description of your command:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-help-description.7f710c984c66.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/discord-bot-help-description.7f710c984c66.png&quot; width=&quot;3030&quot; height=&quot;1771&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-help-description.7f710c984c66.png&amp;amp;w=757&amp;amp;sig=183786aba9f5ba8b48f494d4403adfc38436116d 757w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-help-description.7f710c984c66.png&amp;amp;w=1515&amp;amp;sig=9fde033f6aae07bf16a859ca882fd6b5ffbcf574 1515w, https://files.realpython.com/media/discord-bot-help-description.7f710c984c66.png 3030w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Informative Help Description&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Keep in mind that all of this functionality exists only for the &lt;code&gt;Bot&lt;/code&gt; subclass, not the &lt;code&gt;Client&lt;/code&gt; superclass.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Command&lt;/code&gt; has another useful functionality: the ability to use a &lt;code&gt;Converter&lt;/code&gt; to change the types of its arguments.&lt;/p&gt;
&lt;h3 id=&quot;converting-parameters-automatically&quot;&gt;Converting Parameters Automatically&lt;/h3&gt;
&lt;p&gt;Another benefit of using commands is the ability to &lt;strong&gt;convert&lt;/strong&gt; parameters.&lt;/p&gt;
&lt;p&gt;Sometimes, you require a parameter to be a certain type, but arguments to a &lt;code&gt;Command&lt;/code&gt; function are, by default, strings. A &lt;a href=&quot;https://discordpy.readthedocs.io/en/latest/ext/commands/commands.html#converters&quot;&gt;&lt;code&gt;Converter&lt;/code&gt;&lt;/a&gt; lets you convert those parameters to the type that you expect.&lt;/p&gt;
&lt;p&gt;For example, if you want to build a &lt;code&gt;Command&lt;/code&gt; for your bot user to simulate rolling some dice (knowing what you&amp;rsquo;ve learned so far), you might define it 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;nd&quot;&gt;@bot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&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;s1&quot;&gt;&amp;#39;roll_dice&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Simulates rolling dice.&amp;#39;&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;roll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_of_dice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_of_sides&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;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;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_of_sides&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;number_of_dice&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;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&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;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;dice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You defined &lt;code&gt;roll&lt;/code&gt; to take two parameters:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The number of dice to roll&lt;/li&gt;
&lt;li&gt;The number of sides per die&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then, you decorated it with &lt;code&gt;.command()&lt;/code&gt; so that you can invoke it with the &lt;code&gt;!roll_dice&lt;/code&gt; command. Finally, you &lt;code&gt;.send()&lt;/code&gt; the results in a message back to the &lt;code&gt;channel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;While this looks correct, it isn&amp;rsquo;t. Unfortunately, if you run &lt;code&gt;bot.py&lt;/code&gt;, and invoke the &lt;code&gt;!roll_dice&lt;/code&gt; command in your Discord channel, you&amp;rsquo;ll see the following 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; python bot.py
&lt;span class=&quot;go&quot;&gt;Ignoring exception in command roll_dice:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py&amp;quot;, line 63, in wrapped&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    ret = await coro(*args, **kwargs)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;bot.py&amp;quot;, line 40, in roll&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    for _ in range(number_of_dice)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;TypeError: &amp;#39;str&amp;#39; object cannot be interpreted as an integer&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;The above exception was the direct cause of the following exception:&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/bot.py&amp;quot;, line 860, in invoke&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    await ctx.command.invoke(ctx)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py&amp;quot;, line 698, in invoke&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    await injected(*ctx.args, **ctx.kwargs)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py&amp;quot;, line 72, in wrapped&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    raise CommandInvokeError(exc) from exc&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: &amp;#39;str&amp;#39; object cannot be interpreted as an integer&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In other words, &lt;code&gt;range()&lt;/code&gt; can&amp;rsquo;t accept a &lt;code&gt;str&lt;/code&gt; as an argument. Instead, it must be an &lt;code&gt;int&lt;/code&gt;. While you could cast each value to an &lt;code&gt;int&lt;/code&gt;, there is a better way: you can use a &lt;code&gt;Converter&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;discord.py&lt;/code&gt;, a &lt;code&gt;Converter&lt;/code&gt; is defined using Python 3&amp;rsquo;s &lt;a href=&quot;https://realpython.com/python-type-checking/#annotations&quot;&gt;function annotations&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;nd&quot;&gt;@bot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&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;s1&quot;&gt;&amp;#39;roll_dice&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Simulates rolling dice.&amp;#39;&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;roll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_of_dice&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;number_of_sides&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;dice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;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;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_of_sides&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;number_of_dice&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;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&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;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;dice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You added &lt;code&gt;: int&lt;/code&gt; annotations to the two parameters that you expect to be of type &lt;code&gt;int&lt;/code&gt;. Try the command again:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-roll-dice.0255e76f078e.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/discord-bot-roll-dice.0255e76f078e.png&quot; width=&quot;3025&quot; height=&quot;1769&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-roll-dice.0255e76f078e.png&amp;amp;w=756&amp;amp;sig=ab57569c628b33d801c556a37291da4c2bf38898 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-roll-dice.0255e76f078e.png&amp;amp;w=1512&amp;amp;sig=561a833205a5df4d50976436b4640f10942e6be3 1512w, https://files.realpython.com/media/discord-bot-roll-dice.0255e76f078e.png 3025w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Bot Dice-Rolling Command&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With that little change, your command works! The difference is that you&amp;rsquo;re now converting the command arguments to &lt;code&gt;int&lt;/code&gt;, which makes them compatible with your function&amp;rsquo;s logic.&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;code&gt;Converter&lt;/code&gt; can be any callable, not merely data types. The argument will be passed to the callable, and the return value will be passed into the &lt;code&gt;Command&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Next, you&amp;rsquo;ll learn about the &lt;code&gt;Check&lt;/code&gt; object and how it can improve your commands.&lt;/p&gt;
&lt;h3 id=&quot;checking-command-predicates&quot;&gt;Checking Command Predicates&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;Check&lt;/code&gt; is a predicate that is evaluated before a &lt;code&gt;Command&lt;/code&gt; is executed to ensure that the &lt;code&gt;Context&lt;/code&gt; surrounding the &lt;code&gt;Command&lt;/code&gt; invocation is valid.&lt;/p&gt;
&lt;p&gt;In an earlier example, you did something similar to verify that the user who sent a message that the bot handles was not the bot user, itself:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;commands&lt;/code&gt; extension provides a cleaner and more usable mechanism for performing this kind of check, namely using &lt;code&gt;Check&lt;/code&gt; objects.&lt;/p&gt;
&lt;p&gt;To demonstrate how this works, assume you want to support a command &lt;code&gt;!create_channel &amp;lt;channel_name&amp;gt;&lt;/code&gt; that creates a new channel. However, you only want to allow administrators the ability to create new channels with this command.&lt;/p&gt;
&lt;p&gt;First, you&amp;rsquo;ll need to create a new member role in the admin. Go into the Discord guild and select the &lt;em&gt;{Server Name} → Server Settings&lt;/em&gt; menu:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-server-settings.1eb7e71e881b.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/discord-bot-server-settings.1eb7e71e881b.png&quot; width=&quot;3023&quot; height=&quot;1768&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-server-settings.1eb7e71e881b.png&amp;amp;w=755&amp;amp;sig=65edbf90c63743f93f195bb32661ebd7dc8c453f 755w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-server-settings.1eb7e71e881b.png&amp;amp;w=1511&amp;amp;sig=9576ffae79458bead937645d0d0fc693e91c9972 1511w, https://files.realpython.com/media/discord-bot-server-settings.1eb7e71e881b.png 3023w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Server Settings Screen&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then, select &lt;em&gt;Roles&lt;/em&gt; from the left-hand navigation list:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-roles.bdc21374afa9.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/discord-bot-roles.bdc21374afa9.png&quot; width=&quot;3002&quot; height=&quot;1769&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-roles.bdc21374afa9.png&amp;amp;w=750&amp;amp;sig=c9353734130e1c77c2e9022990b89f79db8806b7 750w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-roles.bdc21374afa9.png&amp;amp;w=1501&amp;amp;sig=c990b12b692cfdee8eccd91f8dec3e70e1977a67 1501w, https://files.realpython.com/media/discord-bot-roles.bdc21374afa9.png 3002w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Navigate to Roles&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally select the &lt;em&gt;+&lt;/em&gt; sign next to &lt;em&gt;ROLES&lt;/em&gt; and enter the name &lt;code&gt;admin&lt;/code&gt; and select &lt;em&gt;Save Changes&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-new-role.7e8d95291d0d.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/discord-bot-new-role.7e8d95291d0d.png&quot; width=&quot;3027&quot; height=&quot;1767&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-new-role.7e8d95291d0d.png&amp;amp;w=756&amp;amp;sig=f69a116bd35511e1c5b1b70d26b96c483d0f723e 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-new-role.7e8d95291d0d.png&amp;amp;w=1513&amp;amp;sig=3d883a2bb6f60a880175c06d523790ca07cc208c 1513w, https://files.realpython.com/media/discord-bot-new-role.7e8d95291d0d.png 3027w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Create New Admin Role&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, you&amp;rsquo;ve created an &lt;code&gt;admin&lt;/code&gt; role that you can assign to particular users. Next, you&amp;rsquo;ll update &lt;code&gt;bot.py&lt;/code&gt; to &lt;code&gt;Check&lt;/code&gt; the user&amp;rsquo;s role before allowing them to initiate the command:&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;# bot.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;discord.ext&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load_dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;DISCORD_TOKEN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command_prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@bot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&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;s1&quot;&gt;&amp;#39;create-channel&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@commands&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;has_role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;admin&amp;#39;&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;create_channel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channel_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;real-python&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;guild&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guild&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;existing_channel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;existing_channel&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;Creating a new channel: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{channel_name}&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;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_text_channel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bot&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;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;bot.py&lt;/code&gt;, you have a new &lt;code&gt;Command&lt;/code&gt; function, called &lt;code&gt;create_channel()&lt;/code&gt; which takes an optional &lt;code&gt;channel_name&lt;/code&gt; and creates that channel. &lt;code&gt;create_channel()&lt;/code&gt; is also decorated with a &lt;code&gt;Check&lt;/code&gt; called &lt;code&gt;has_role()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You also use &lt;code&gt;discord.utils.get()&lt;/code&gt; to ensure that you don&amp;rsquo;t create a channel with the same name as an existing channel.&lt;/p&gt;
&lt;p&gt;If you run this program as it is and type &lt;code&gt;!create-channel&lt;/code&gt; into your Discord channel, then you&amp;rsquo;ll see the following error message:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python bot.py
&lt;span class=&quot;go&quot;&gt;Ignoring exception in command create-channel:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/bot.py&amp;quot;, line 860, in invoke&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    await ctx.command.invoke(ctx)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py&amp;quot;, line 691, in invoke&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    await self.prepare(ctx)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py&amp;quot;, line 648, in prepare&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    await self._verify_checks(ctx)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py&amp;quot;, line 598, in _verify_checks&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    raise CheckFailure(&amp;#39;The check functions for command {0.qualified_name} failed.&amp;#39;.format(self))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;discord.ext.commands.errors.CheckFailure: The check functions for command create-channel failed.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This &lt;code&gt;CheckFailure&lt;/code&gt; says that &lt;code&gt;has_role(&#39;admin&#39;)&lt;/code&gt; failed. Unfortunately, this error only prints to &lt;code&gt;stdout&lt;/code&gt;. It would be better to report this to the user in the channel. To do so, add the following event:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@bot&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;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;on_command_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CheckFailure&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;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;You do not have the correct role for this command.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This event handles an error event from the command and sends an informative error message back to the original &lt;code&gt;Context&lt;/code&gt; of the invoked &lt;code&gt;Command&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Try it all again, and you should see an error in the Discord channel:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-role-error-message.adfe85fe76a9.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/discord-bot-role-error-message.adfe85fe76a9.png&quot; width=&quot;3028&quot; height=&quot;1768&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-role-error-message.adfe85fe76a9.png&amp;amp;w=757&amp;amp;sig=f4c4c8c318e4079b634fd089dfbdbc14524de8d8 757w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-role-error-message.adfe85fe76a9.png&amp;amp;w=1514&amp;amp;sig=0ac21290b0674b8954a40c6a92c0e14c04a8ca78 1514w, https://files.realpython.com/media/discord-bot-role-error-message.adfe85fe76a9.png 3028w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Role Check Error&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Great! Now, to resolve the issue, you&amp;rsquo;ll need to give yourself the &lt;em&gt;admin&lt;/em&gt; role:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-role-granted.081c0c317834.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/discord-bot-role-granted.081c0c317834.png&quot; width=&quot;3026&quot; height=&quot;1767&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-role-granted.081c0c317834.png&amp;amp;w=756&amp;amp;sig=d2cb8f8765ffd8fc574808a810170c267e06069f 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-role-granted.081c0c317834.png&amp;amp;w=1513&amp;amp;sig=33fb00357b97007f92ee8fa88ecadfdcecdb09f9 1513w, https://files.realpython.com/media/discord-bot-role-granted.081c0c317834.png 3026w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Grant Admin Role&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With the &lt;em&gt;admin&lt;/em&gt; role, your user will pass the &lt;code&gt;Check&lt;/code&gt; and will be able to create channels using the command.&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; Keep in mind that in order to assign a role, your user will have to have the correct permissions. The easiest way to ensure this is to sign in with the user that you created the guild with.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;When you type &lt;code&gt;!create-channel&lt;/code&gt; again, you&amp;rsquo;ll successfully create the channel &lt;em&gt;real-python&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/discord-bot-new-channel.43cd2889446c.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/discord-bot-new-channel.43cd2889446c.png&quot; width=&quot;3026&quot; height=&quot;1768&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-new-channel.43cd2889446c.png&amp;amp;w=756&amp;amp;sig=768abb1b230e675f2d0b864311f357eff67414b2 756w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/discord-bot-new-channel.43cd2889446c.png&amp;amp;w=1513&amp;amp;sig=ee91b1a9895a80fa1d326de58e6e5b8ac4fd1719 1513w, https://files.realpython.com/media/discord-bot-new-channel.43cd2889446c.png 3026w&quot; sizes=&quot;75vw&quot; alt=&quot;Discord: Navigate to New Channel&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, note that you can pass the optional &lt;code&gt;channel_name&lt;/code&gt; argument to name the channel to whatever you want!&lt;/p&gt;
&lt;p&gt;With this last example, you combined a &lt;code&gt;Command&lt;/code&gt;, an event, a &lt;code&gt;Check&lt;/code&gt;, and even the &lt;code&gt;get()&lt;/code&gt; utility to create a useful Discord bot!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations! Now, you&amp;rsquo;ve learned how to make a Discord bot in Python. You&amp;rsquo;re able to build bots for interacting with users in guilds that you create or even bots that other users can invite to interact with their communities. Your bots will be able to respond to messages and commands and numerous other events.&lt;/p&gt;
&lt;p&gt;In this tutorial, you learned the basics of creating your own Discord bot. You now know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What Discord is&lt;/li&gt;
&lt;li&gt;Why &lt;code&gt;discord.py&lt;/code&gt; is so valuable&lt;/li&gt;
&lt;li&gt;How to make a Discord bot in the Developer Portal&lt;/li&gt;
&lt;li&gt;How to create a Discord connection in Python&lt;/li&gt;
&lt;li&gt;How to handle events&lt;/li&gt;
&lt;li&gt;How to create a &lt;code&gt;Bot&lt;/code&gt; connection&lt;/li&gt;
&lt;li&gt;How to use bot commands, checks, and converters&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To read more about the powerful &lt;code&gt;discord.py&lt;/code&gt; library and take your bots to the next level, read through their extensive &lt;a href=&quot;https://discordapp.com/developers/docs/intro&quot;&gt;documentation&lt;/a&gt;. Also, now that you&amp;rsquo;re familiar with Discord APIs in general, you have a better foundation for building other types of Discord applications.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>An Effective Python Environment: Making Yourself at Home</title>
      <id>https://realpython.com/effective-python-environment/</id>
      <link href="https://realpython.com/effective-python-environment/"/>
      <updated>2019-08-14T14:00:00+00:00</updated>
      <summary>This guide will walk you through the decisions you need to make when customizing your development environment for working with Python.</summary>
      <content type="html">
        &lt;p&gt;When you&amp;rsquo;re first learning a new programming language, a lot of your time and effort go into understanding the syntax, code style, and built-in tooling. This is just as true for Python as it is for any other language. Once you gain enough familiarity to be comfortable with the ins and outs of Python, you can start to invest time into building a Python environment that will foster your productivity.&lt;/p&gt;
&lt;p&gt;Your shell is more than a prebuilt program provided to you as-is. It&amp;rsquo;s a framework on which you can build an ecosystem. This ecosystem will come to fit your needs so that you can spend less time fiddling and more time thinking about the next big project you&amp;rsquo;re working on.&lt;/p&gt;
&lt;p&gt;Although no two developers have the same setup, there are a number of choices everyone faces when cultivating their Python environment. It&amp;rsquo;s important to understand each of these decisions and the options available to you!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this article, you&amp;rsquo;ll be able to answer questions like:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What shell should I use? What terminal should I use?&lt;/li&gt;
&lt;li&gt;What version(s) of Python can I use?&lt;/li&gt;
&lt;li&gt;How do I manage dependencies for different projects?&lt;/li&gt;
&lt;li&gt;How can I make my tools do some of the work for me?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you&amp;rsquo;ve answered these questions for yourself, you can embark on the journey of creating a Python environment to call your very own. 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-dependency-pitfalls-email-course&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a free 5-day class&lt;/a&gt; that shows you how to avoid common dependency management issues with tools like Pip, PyPI, Virtualenv, and requirements files.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;shells&quot;&gt;Shells&lt;/h2&gt;
&lt;p&gt;When you use a &lt;a href=&quot;https://realpython.com/command-line-interfaces-python-argparse/#what-is-a-command-line-interface&quot;&gt;command-line interface&lt;/a&gt; (CLI), you execute commands and see their output. A &lt;strong&gt;shell&lt;/strong&gt; is a program that provides this (usually text-based) interface to you. Shells often provide their own programming language that you can use to manipulate files, install software, and so on.&lt;/p&gt;
&lt;p&gt;There are more unique shells than could be reasonably listed here, so you&amp;rsquo;ll see a few prominent ones. Others differ in syntax or enhanced features, but they generally provide the same core functionality.&lt;/p&gt;
&lt;h3 id=&quot;unix-shells&quot;&gt;Unix Shells&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; is a family of operating systems first developed in the early days of computing. Unix&amp;rsquo;s popularity has lasted through today, heavily inspiring Linux and macOS. The first shells were developed for use with Unix and Unix-like operating systems.&lt;/p&gt;
&lt;h4 id=&quot;bourne-shell-sh&quot;&gt;Bourne Shell (&lt;code&gt;sh&lt;/code&gt;)&lt;/h4&gt;
&lt;p&gt;The Bourne shell&amp;mdash;developed by Stephen Bourne for Bell Labs in 1979&amp;mdash;was one of the first to incorporate the idea of environment variables, conditionals, and loops. It has  provided a strong basis for many other shells in use today and is still available on most systems at &lt;code&gt;/bin/sh&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&quot;bourne-again-shell-bash&quot;&gt;Bourne-Again Shell (&lt;code&gt;bash&lt;/code&gt;)&lt;/h4&gt;
&lt;p&gt;Built on the success of the original Bourne shell, &lt;code&gt;bash&lt;/code&gt; introduced improved user-interaction features. With &lt;code&gt;bash&lt;/code&gt;, you get &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-tab&quot;&gt;Tab&lt;/kbd&gt;&lt;/span&gt; completion, history, and wildcard searching for commands and paths. The &lt;code&gt;bash&lt;/code&gt; programming language provides more data types, like arrays.&lt;/p&gt;
&lt;h4 id=&quot;z-shell-zsh&quot;&gt;Z Shell (&lt;code&gt;zsh&lt;/code&gt;)&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;zsh&lt;/code&gt; combines many of the best features from other shells along with a few of its own tricks into one experience. &lt;code&gt;zsh&lt;/code&gt; offers autocorrection of misspelled commands, shorthand for manipulating multiple files, and advanced options for customizing your command prompt.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zsh&lt;/code&gt; also provides a framework for deep customization. The &lt;a href=&quot;https://ohmyz.sh&quot;&gt;Oh My Zsh&lt;/a&gt; project supplies a rich set of themes and plugins, and is often used hand in hand with &lt;code&gt;zsh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://support.apple.com/en-us/HT208050&quot;&gt;macOS will ship with &lt;code&gt;zsh&lt;/code&gt; as its default shell starting with Catalina&lt;/a&gt;, speaking to the shell&amp;rsquo;s popularity. Consider acquainting yourself with &lt;code&gt;zsh&lt;/code&gt; now so that you&amp;rsquo;ll be comfortable with it going forward.&lt;/p&gt;
&lt;h4 id=&quot;xonsh&quot;&gt;Xonsh&lt;/h4&gt;
&lt;p&gt;If you&amp;rsquo;re feeling particularly adventurous, you can give &lt;a href=&quot;https://xon.sh&quot;&gt;Xonsh&lt;/a&gt; a try. Xonsh is a shell that combines some features of other Unix-like shells with the power of Python syntax. You can use the language you already know to accomplish tasks on your filesystem and so on.&lt;/p&gt;
&lt;p&gt;Although Xonsh is powerful, it lacks the compatibility other shells tend to share. You might not be able to run many existing shell scripts in Xonsh as a result. If you find that you like Xonsh, but compatibility is a concern, then you can use Xonsh as a supplement to your activities in a more widely used shell.&lt;/p&gt;
&lt;h3 id=&quot;windows-shells&quot;&gt;Windows Shells&lt;/h3&gt;
&lt;p&gt;Similarly to Unix-like operating systems, Windows also offers a number of options when it comes to shells. The shells offered in Windows vary in features and syntax, so you may need to try several to find one you like best.&lt;/p&gt;
&lt;h4 id=&quot;cmd-cmdexe&quot;&gt;CMD (&lt;code&gt;cmd.exe&lt;/code&gt;)&lt;/h4&gt;
&lt;p&gt;CMD (short for &amp;ldquo;command&amp;rdquo;) is the default CLI shell for Windows. It&amp;rsquo;s the successor to COMMAND.COM, the shell built for DOS (disk operating system).&lt;/p&gt;
&lt;p&gt;Because DOS and Unix evolved independently, the commands and syntax in CMD are markedly different from shells built for Unix-like systems. However, CMD still provides the same core functionality for browsing and manipulating files, running commands, and viewing output.&lt;/p&gt;
&lt;h4 id=&quot;powershell&quot;&gt;PowerShell&lt;/h4&gt;
&lt;p&gt;PowerShell was released in 2006 and also ships with Windows. It provides Unix-like aliases for most commands, so if you&amp;rsquo;re coming to Windows from macOS or Linux or have to use both, then PowerShell might be great for you.&lt;/p&gt;
&lt;p&gt;PowerShell is vastly more powerful than CMD. With PowerShell you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pipe the output of one command to the input of another&lt;/li&gt;
&lt;li&gt;Automate tasks through the exposed Windows management features&lt;/li&gt;
&lt;li&gt;Use a scripting language to accomplish complex tasks&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;windows-subsystem-for-linux&quot;&gt;Windows Subsystem for Linux&lt;/h4&gt;
&lt;p&gt;Microsoft has released a &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/wsl/install-win10&quot;&gt;Windows subsystem for Linux&lt;/a&gt; (WSL) for running Linux directly on Windows. If you install WSL, then you can use &lt;code&gt;zsh&lt;/code&gt;, &lt;code&gt;bash&lt;/code&gt;, or any other Unix-like shell. If you want strong compatibility across your Windows and macOS or Linux environments, then be sure to give WSL a try. You may also consider &lt;a href=&quot;https://opensource.com/article/18/5/dual-boot-linux&quot;&gt;dual-booting Linux and Windows&lt;/a&gt; as an alternative.&lt;/p&gt;
&lt;p&gt;See this &lt;a href=&quot;https://en.wikipedia.org/wiki/Comparison_of_command_shells&quot;&gt;comparison of command shells&lt;/a&gt; for exhaustive coverage.&lt;/p&gt;
&lt;h2 id=&quot;terminal-emulators&quot;&gt;Terminal Emulators&lt;/h2&gt;
&lt;p&gt;Early developers used &lt;strong&gt;terminals&lt;/strong&gt; to interact with a central mainframe computer. These were devices with a keyboard and a screen or printer that would display computed output.&lt;/p&gt;
&lt;p&gt;Today, computers are portable and don&amp;rsquo;t require separate devices to interact with them, but the terminology still remains. Whereas a shell provides the prompt and interpreter you use to interface with text-based CLI tools, a terminal &lt;strong&gt;emulator&lt;/strong&gt; (often shortened to &lt;strong&gt;terminal&lt;/strong&gt;) is the graphical application you run to access the shell.&lt;/p&gt;
&lt;p&gt;Almost any terminal you encounter should support the same basic features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Text colors&lt;/strong&gt; for syntax highlighting in your code or distinguishing meaningful text in command output&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scrolling&lt;/strong&gt; for viewing an earlier command or its output&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copy/paste&lt;/strong&gt; for transferring text in or out of the shell from other programs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tabs&lt;/strong&gt; for running multiple programs at once or separating your work into different sessions&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;macos-terminals&quot;&gt;macOS Terminals&lt;/h3&gt;
&lt;p&gt;The terminal options available for macOS are all full-featured, differing mostly in aesthetics and specific integrations with other tools.&lt;/p&gt;
&lt;h4 id=&quot;terminal&quot;&gt;Terminal&lt;/h4&gt;
&lt;p&gt;If you&amp;rsquo;re using a Mac, then you may have used the built-in &lt;a href=&quot;https://support.apple.com/guide/terminal/welcome/mac&quot;&gt;Terminal&lt;/a&gt; app before. Terminal supports all the usual functionality, and you can also customize the color scheme and a few hotkeys. It&amp;rsquo;s a nice enough tool if you don&amp;rsquo;t need many bells and whistles. You can find the Terminal app in &lt;em&gt;Applications &amp;rarr; Utilities &amp;rarr; Terminal&lt;/em&gt; on macOS.&lt;/p&gt;
&lt;h4 id=&quot;iterm2&quot;&gt;iTerm2&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;ve been a long-time user of &lt;a href=&quot;https://iterm2.com&quot;&gt;iTerm2&lt;/a&gt;. It takes the developer experience on Mac a step further, offering a much wider palette of customization and productivity options that enable you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integrate with the shell to jump quickly to previously entered commands&lt;/li&gt;
&lt;li&gt;Create custom search term highlighting in the output from commands&lt;/li&gt;
&lt;li&gt;Open URLs and files displayed in the terminal with &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-command&quot;&gt;Cmd&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd&gt;click&lt;/kbd&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A Python API ships with the latest versions of iTerm2, so you can even improve your Python chops by developing more intricate customizations!&lt;/p&gt;
&lt;p&gt;iTerm2 is popular enough to enjoy first-class integration with several other tools, and has a healthy community building plugins and so on. It&amp;rsquo;s a good choice because of its more frequent release cycle compared to Terminal, which only updates as often as macOS does.&lt;/p&gt;
&lt;h4 id=&quot;hyper&quot;&gt;Hyper&lt;/h4&gt;
&lt;p&gt;A relative newcomer, &lt;a href=&quot;https://hyper.is/&quot;&gt;Hyper&lt;/a&gt; is a terminal built on &lt;a href=&quot;https://electronjs.org/&quot;&gt;Electron&lt;/a&gt;, a framework for building desktop applications using web technologies. Electron apps are heavily customizable because they&amp;rsquo;re &amp;ldquo;just JavaScript&amp;rdquo; under the hood. You can create any functionality that you can write the JavaScript for.&lt;/p&gt;
&lt;p&gt;On the other hand, JavaScript is a high-level programming language and won&amp;rsquo;t always perform as well as low-level languages like Objective-C or Swift. Be mindful of the plugins you install or create!&lt;/p&gt;
&lt;h3 id=&quot;windows-terminals&quot;&gt;Windows Terminals&lt;/h3&gt;
&lt;p&gt;As with the shell options, Windows terminal options vary widely in utility. Some are tightly bound to a particular shell as well.&lt;/p&gt;
&lt;h4 id=&quot;command-prompt&quot;&gt;Command Prompt&lt;/h4&gt;
&lt;p&gt;Command Prompt is the graphical application you can use to work with CMD in Windows. Like CMD, it&amp;rsquo;s a bare-bones tool for getting a few small things done. Although Command Prompt and CMD provide fewer features than other alternatives, you can be confident that they&amp;rsquo;ll be available on nearly every Windows installation and in a consistent place.&lt;/p&gt;
&lt;h4 id=&quot;cygwin&quot;&gt;Cygwin&lt;/h4&gt;
&lt;p&gt;Cygwin is a third-party suite of tools for Windows that provides a Unix-like wrapper. This was my preferred setup when I was in Windows, but you may consider adopting the Windows Subsystem for Linux as it receives more traction and polish.&lt;/p&gt;
&lt;h4 id=&quot;windows-terminal&quot;&gt;Windows Terminal&lt;/h4&gt;
&lt;p&gt;Microsoft recently released an open source terminal for Windows 10 called &lt;a href=&quot;https://github.com/Microsoft/Terminal&quot;&gt;Windows Terminal&lt;/a&gt;. It lets you work in CMD, PowerShell, and even the Windows Subsystem for Linux. If you need to do a fair amount of shell work in Windows, then Windows Terminal is probably your best bet! Windows Terminal is still in late beta, so it doesn&amp;rsquo;t ship with Windows yet. Check the documentation for instructions on getting access.&lt;/p&gt;
&lt;h2 id=&quot;python-version-management&quot;&gt;Python Version Management&lt;/h2&gt;
&lt;p&gt;With your choice of terminal and shell made, you can focus your attention on your Python environment specifically.&lt;/p&gt;
&lt;p&gt;Something you&amp;rsquo;ll eventually run into is the need to run multiple &lt;strong&gt;versions&lt;/strong&gt; of Python. Projects you use may only run on certain versions, or you may be interested in creating a project that supports multiple Python versions. You can configure your Python environment to accommodate these needs.&lt;/p&gt;
&lt;p&gt;macOS and most Unix operating systems come with a version of Python installed by default. This is often called the &lt;strong&gt;system Python&lt;/strong&gt;. The system Python works just fine, but it&amp;rsquo;s usually out of date. As of this writing, macOS High Sierra still ships with Python 2.7.10 as the system Python.&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 almost certainly want to install the latest version of Python at a minimum, so you&amp;rsquo;ll have at least two versions of Python already. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It&amp;rsquo;s important that you leave the system Python as the default&lt;/strong&gt;, because many parts of the system rely on the default Python being a specific version. This is one of many great reasons to customize your Python environment!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;How do you navigate this? Tooling is here to help.&lt;/p&gt;
&lt;h3 id=&quot;pyenv&quot;&gt;&lt;code&gt;pyenv&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pyenv/pyenv&quot;&gt;&lt;code&gt;pyenv&lt;/code&gt;&lt;/a&gt; is a mature tool for installing and managing multiple Python versions on macOS. I recommend &lt;a href=&quot;https://github.com/pyenv/pyenv#homebrew-on-macos&quot;&gt;installing it with Homebrew&lt;/a&gt;. If you&amp;rsquo;re using Windows, you can use &lt;a href=&quot;https://github.com/pyenv-win/pyenv-win#installation&quot;&gt;&lt;code&gt;pyenv-win&lt;/code&gt;&lt;/a&gt;. After you&amp;rsquo;ve got &lt;code&gt;pyenv&lt;/code&gt; installed, you can install multiple versions of Python into your Python environment with a few short 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; pyenv versions
&lt;span class=&quot;go&quot;&gt;* system&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python --version
&lt;span class=&quot;go&quot;&gt;Python 2.7.10&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv install &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3  &lt;span class=&quot;c1&quot;&gt;# This may take some time&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv versions
&lt;span class=&quot;go&quot;&gt;* system&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  3.7.3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can manage which Python you&amp;rsquo;d like to use in your current session, globally, or on a per-project basis as well. &lt;code&gt;pyenv&lt;/code&gt; will make the &lt;code&gt;python&lt;/code&gt; command point to whichever Python you specify. Note that none of these overrides the default system Python for other applications, so you&amp;rsquo;re safe to use them however they work best for you within your Python 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; pyenv global &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv versions
&lt;span class=&quot;go&quot;&gt;  system&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;* 3.7.3 (set by /Users/dhillard/.pyenv/version)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv versions
&lt;span class=&quot;go&quot;&gt;  system&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;* 3.7.3 (set by /Users/dhillard/myproj/.python-version)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv shell &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv versions
&lt;span class=&quot;go&quot;&gt;  system&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;* 3.7.3 (set by PYENV_VERSION environment variable)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python --version
&lt;span class=&quot;go&quot;&gt;Python 3.7.3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because I use a specific version of Python for work, the latest version of Python for personal projects, and multiple versions for testing open source projects, &lt;code&gt;pyenv&lt;/code&gt; has proven to be a fairly smooth way for me to manage all these different versions within my own Python environment. See &lt;a href=&quot;https://realpython.com/intro-to-pyenv/&quot;&gt;Managing Multiple Python Versions with &lt;code&gt;pyenv&lt;/code&gt;&lt;/a&gt; for a detailed overview of the tool.&lt;/p&gt;
&lt;h3 id=&quot;conda&quot;&gt;&lt;code&gt;conda&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re in the data science community, you might already be using &lt;a href=&quot;https://www.anaconda.com/distribution/&quot;&gt;Anaconda&lt;/a&gt; (or &lt;a href=&quot;https://docs.conda.io/en/latest/miniconda.html&quot;&gt;Miniconda&lt;/a&gt;). Anaconda is a sort of one-stop shop for data science software that supports more than just Python.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t need the data science packages or all the things that come pre-packaged with Anaconda, &lt;code&gt;pyenv&lt;/code&gt; might be a better lightweight solution for you. Managing Python versions is pretty similar in each, though. You can install Python versions similarly to &lt;code&gt;pyenv&lt;/code&gt;, using the &lt;code&gt;conda&lt;/code&gt; 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; conda install &lt;span class=&quot;nv&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll see a verbose list of all the dependent software &lt;code&gt;conda&lt;/code&gt; will install, and it will ask you to confirm.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;conda&lt;/code&gt; doesn&amp;rsquo;t have a way to set the &amp;ldquo;default&amp;rdquo; Python version or even a good way to see which versions of Python you&amp;rsquo;ve installed. Rather, it hinges on the concept of &amp;ldquo;environments,&amp;rdquo; which you can read more about in the following sections.&lt;/p&gt;
&lt;h2 id=&quot;virtual-environments&quot;&gt;Virtual Environments&lt;/h2&gt;
&lt;p&gt;Now you know how to manage multiple Python versions. Often, you&amp;rsquo;ll be working on multiple projects that need the &lt;em&gt;same&lt;/em&gt; Python version.&lt;/p&gt;
&lt;p&gt;Because each project has its own set of dependencies, it&amp;rsquo;s a good practice to avoid mixing them. If all the dependencies are installed together in a single Python environment, then it will be difficult to discern where each one came from. In the worst cases, two different projects may depend on two different versions of a package, but with Python you can only have one version of a package installed at one time. What a mess!&lt;/p&gt;
&lt;p&gt;Enter &lt;strong&gt;virtual environments&lt;/strong&gt;. You can think of a virtual environment as a carbon copy of a base version of Python. If you&amp;rsquo;ve installed Python 3.7.3, for example, then you can create many virtual environments based off of it. When you install a package in a virtual environment, you do it in isolation from other Python environments you may have. Each virtual environment has its own copy of the &lt;code&gt;python&lt;/code&gt; executable.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Most virtual environment tooling provides a way to update your shell&amp;rsquo;s command prompt to show the current active virtual environment. Make sure to do this if you frequently switch between projects so you&amp;rsquo;re sure you&amp;rsquo;re working inside the correct virtual environment.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;venv&quot;&gt;&lt;code&gt;venv&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot;&gt;&lt;code&gt;venv&lt;/code&gt;&lt;/a&gt; ships with Python versions 3.3+. You can create virtual environments just by passing it a path at which to store the environment&amp;rsquo;s &lt;code&gt;python&lt;/code&gt;, installed packages, and so on:&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 venv ~/.virtualenvs/my-env
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You activate a virtual environment by sourcing its &lt;code&gt;activate&lt;/code&gt; script:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.virtualenvs/my-env/bin/activate
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You exit the virtual environment using the &lt;code&gt;deactivate&lt;/code&gt; command, which is made available when you activate the 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;(my-env)$&lt;/span&gt; deactivate
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;venv&lt;/code&gt; is built on the wonderful work and successes of the independent &lt;a href=&quot;https://virtualenv.pypa.io/en/stable/&quot;&gt;&lt;code&gt;virtualenv&lt;/code&gt;&lt;/a&gt; project. &lt;code&gt;virtualenv&lt;/code&gt; still provides a few interesting features of its own, but &lt;code&gt;venv&lt;/code&gt; is nice because it provides the utility of virtual environments without requiring you to install additional software. You can probably get pretty far with it if you&amp;rsquo;re working mostly in a single Python version in your Python environment.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re already managing multiple Python versions (or plan to), then it could make sense to integrate with that tooling to simplify the process of making new virtual environments with specific versions of Python. The &lt;code&gt;pyenv&lt;/code&gt; and &lt;code&gt;conda&lt;/code&gt; ecosystems both provide ways to specify the Python version to use when you create new virtual environments, covered in the following sections.&lt;/p&gt;
&lt;h3 id=&quot;pyenv-virtualenv&quot;&gt;&lt;code&gt;pyenv-virtualenv&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re using &lt;code&gt;pyenv&lt;/code&gt;, then &lt;a href=&quot;https://github.com/pyenv/pyenv-virtualenv&quot;&gt;&lt;code&gt;pyenv-virtualenv&lt;/code&gt;&lt;/a&gt; enhances &lt;code&gt;pyenv&lt;/code&gt; with a subcommand for managing virtual environments:&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;// Create virtual environment&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv virtualenv &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3 my-env

&lt;span class=&quot;go&quot;&gt;// Activate virtual environment&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv activate my-env

&lt;span class=&quot;go&quot;&gt;// Exit virtual environment&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;(my-env)$&lt;/span&gt; pyenv deactivate
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I switch contexts between a large handful of projects on a day-to-day basis. As a result, I have at least a dozen distinct virtual environments to manage in my Python environment. What&amp;rsquo;s really nice about &lt;code&gt;pyenv-virtualenv&lt;/code&gt; is that you can configure a virtual environment using the &lt;code&gt;pyenv local&lt;/code&gt; command and have &lt;code&gt;pyenv-virtualenv&lt;/code&gt; auto-activate the right environments as you switch to different directories:&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; pyenv virtualenv &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3 proj1
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv virtualenv &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3 proj2
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /Users/dhillard/proj1
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt; proj1
&lt;span class=&quot;gp&quot;&gt;(proj1)$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ../proj2
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt; proj2
&lt;span class=&quot;gp&quot;&gt;(proj2)$&lt;/span&gt; pyenv versions
&lt;span class=&quot;go&quot;&gt;  system&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  3.7.3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  3.7.3/envs/proj1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  3.7.3/envs/proj2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  proj1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;* proj2 (set by /Users/dhillard/proj2/.python-version)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;pyenv&lt;/code&gt; and &lt;code&gt;pyenv-virtualenv&lt;/code&gt; have provided a particularly fluid workflow in my Python environment.&lt;/p&gt;
&lt;h3 id=&quot;conda_1&quot;&gt;&lt;code&gt;conda&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;You saw earlier that &lt;code&gt;conda&lt;/code&gt; treats environments, rather than Python versions, as the main method of working. &lt;a href=&quot;https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html&quot;&gt;&lt;code&gt;conda&lt;/code&gt; has built-in support for managing virtual environments&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;// Create virtual environment&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; conda create --name my-env &lt;span class=&quot;nv&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3

&lt;span class=&quot;go&quot;&gt;// Activate virtual environment&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; conda activate my-env

&lt;span class=&quot;go&quot;&gt;// Exit virtual environment&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;(my-env)$&lt;/span&gt; conda deactivate
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;conda&lt;/code&gt; will install the specified version of Python if it isn&amp;rsquo;t already installed, so you don&amp;rsquo;t have to run &lt;code&gt;conda install python=3.7.3&lt;/code&gt; first.&lt;/p&gt;
&lt;h3 id=&quot;pipenv&quot;&gt;&lt;code&gt;pipenv&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.pipenv.org/en/latest/&quot;&gt;&lt;code&gt;pipenv&lt;/code&gt;&lt;/a&gt; is a relatively new tool that seeks to combine package management (more on this in a moment) with virtual environment management. It mostly abstracts the virtual environment management from you, which can be great as long as things go smoothly:&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; /Users/dhillard/myproj

&lt;span class=&quot;go&quot;&gt;// Create virtual environment&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pipenv install
&lt;span class=&quot;go&quot;&gt;Creating a virtualenv for this project…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Pipfile: /Users/dhillard/myproj/Pipfile&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Using /path/to/pipenv/python3.7 (3.7.3) to create virtualenv…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;✔ Successfully created virtual environment!&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Virtualenv location: /Users/dhillard/.local/share/virtualenvs/myproj-nAbMEAt0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Creating a Pipfile for this project…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Pipfile.lock not found, creating…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Locking [dev-packages] dependencies…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Locking [packages] dependencies…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Updated Pipfile.lock (a65489)!&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Installing dependencies from Pipfile.lock (a65489)…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 00:00:00&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;To activate this project&amp;#39;s virtualenv, run pipenv shell.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Alternatively, run a command inside the virtualenv with pipenv run.&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;// Activate virtual environment (uses a subshell)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pipenv shell
&lt;span class=&quot;go&quot;&gt;Launching subshell in virtual environment…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; . /Users/dhillard/.local/share/virtualenvs/test-nAbMEAt0/bin/activate&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;// Exit virtual environment (by exiting subshell)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;(myproj-nAbMEAt0)$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;pipenv&lt;/code&gt; does all the heavy lifting of creating a virtual environment and activating it for you. If you look carefully, you can see that it also creates a file called &lt;code&gt;Pipfile&lt;/code&gt;. After you first run &lt;code&gt;pipenv install&lt;/code&gt;, this file contains just a few things:&lt;/p&gt;
&lt;div class=&quot;highlight ini&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;[[source]]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;pypi&amp;quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;https://pypi.org/simple&amp;quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;verify_ssl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;[dev-packages]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;[packages]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;[requires]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;python_version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;3.7&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In particular, note that it shows &lt;code&gt;python_version = &quot;3.7&quot;&lt;/code&gt;. By default, &lt;code&gt;pipenv&lt;/code&gt; creates a virtual Python environment using the same Python version it was installed under. If you want to use a different Python version, then you can create the &lt;code&gt;Pipfile&lt;/code&gt; yourself before running &lt;code&gt;pipenv install&lt;/code&gt; and specify the version you want. If you have &lt;code&gt;pyenv&lt;/code&gt; installed, then &lt;code&gt;pipenv&lt;/code&gt; will use it to install the specified Python version if necessary.&lt;/p&gt;
&lt;p&gt;Abstracting virtual environment management is a noble goal of &lt;code&gt;pipenv&lt;/code&gt;, but it does get hung up with hard-to-read errors occasionally. Give it a try, but don&amp;rsquo;t worry if you feel confused or overwhelmed by it. The tool, documentation, and community will grow and improve around it as it matures.&lt;/p&gt;
&lt;p&gt;To get an in-depth introduction to virtual environments, be sure to read &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;h2 id=&quot;package-management&quot;&gt;Package Management&lt;/h2&gt;
&lt;p&gt;For many of the projects you work on, you&amp;rsquo;ll probably need some number of third-party packages. Those packages may have their own dependencies in turn. In the early days of Python, using packages involved manually downloading files and pointing Python at them. Today, we&amp;rsquo;re fortunate to have a variety of package management tools available to us.&lt;/p&gt;
&lt;p&gt;Most package managers work in tandem with virtual environments, isolating the packages you install in one Python environment from another. Using the two together is where you really start to see the power of the tools available to you.&lt;/p&gt;
&lt;h3 id=&quot;pip&quot;&gt;&lt;code&gt;pip&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;pip&lt;/code&gt; (&lt;strong&gt;p&lt;/strong&gt;ip &lt;strong&gt;i&lt;/strong&gt;nstalls &lt;strong&gt;p&lt;/strong&gt;ackages) has been the de facto standard for package management in Python for several years. It was heavily inspired by an earlier tool called &lt;code&gt;easy_install&lt;/code&gt;. Python incorporated &lt;code&gt;pip&lt;/code&gt; into the standard distribution starting in version 3.4. &lt;code&gt;pip&lt;/code&gt; automates the process of downloading packages and making Python aware of them.&lt;/p&gt;
&lt;p&gt;If you have multiple virtual environments, then you can see that they&amp;rsquo;re isolated by installing a few packages in one:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv virtualenv &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7.3 proj1
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pyenv activate proj1
&lt;span class=&quot;gp&quot;&gt;(proj1)$&lt;/span&gt; pip list
&lt;span class=&quot;go&quot;&gt;Package    Version&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;---------- ---------&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pip        19.1.1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;setuptools 40.8.0&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;(proj1)$&lt;/span&gt; python -m pip install requests
&lt;span class=&quot;go&quot;&gt;Collecting requests&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  Downloading .../requests-2.22.0-py2.py3-none-any.whl (57kB)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    100% |████████████████████████████████| 61kB 2.2MB/s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Collecting chardet&amp;lt;3.1.0,&amp;gt;=3.0.2 (from requests)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  Downloading .../chardet-3.0.4-py2.py3-none-any.whl (133kB)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    100% |████████████████████████████████| 143kB 1.7MB/s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Collecting certifi&amp;gt;=2017.4.17 (from requests)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  Downloading .../certifi-2019.6.16-py2.py3-none-any.whl (157kB)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    100% |████████████████████████████████| 163kB 6.0MB/s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Collecting urllib3!=1.25.0,!=1.25.1,&amp;lt;1.26,&amp;gt;=1.21.1 (from requests)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  Downloading .../urllib3-1.25.3-py2.py3-none-any.whl (150kB)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    100% |████████████████████████████████| 153kB 1.7MB/s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Collecting idna&amp;lt;2.9,&amp;gt;=2.5 (from requests)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  Downloading .../idna-2.8-py2.py3-none-any.whl (58kB)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    100% |████████████████████████████████| 61kB 26.6MB/s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Installing collected packages: chardet, certifi, urllib3, idna, requests&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Successfully installed packages&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pip list
&lt;span class=&quot;go&quot;&gt;Package    Version&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;---------- ---------&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;certifi    2019.6.16&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;chardet    3.0.4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;idna       2.8&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pip        19.1.1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;requests   2.22.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;setuptools 40.8.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;urllib3    1.25.3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;pip&lt;/code&gt; installed &lt;code&gt;requests&lt;/code&gt;, along with several packages it depends on. &lt;code&gt;pip list&lt;/code&gt; shows you all the currently installed packages and their versions.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: You can uninstall packages using &lt;code&gt;pip uninstall requests&lt;/code&gt;, for example, but this will &lt;em&gt;only&lt;/em&gt; uninstall &lt;code&gt;requests&lt;/code&gt;&amp;mdash;not any of its dependencies.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;A common way to specify project dependencies for &lt;code&gt;pip&lt;/code&gt; is with a &lt;code&gt;requirements.txt&lt;/code&gt; file. Each line in the file specifies a package name and, optionally, the version to install:&lt;/p&gt;
&lt;div class=&quot;highlight pyreq&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scipy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.3&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;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.22&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can then run &lt;code&gt;python -m pip install -r requirements.txt&lt;/code&gt; to install all of the specified dependencies at once. For more on &lt;code&gt;pip&lt;/code&gt;, see &lt;a href=&quot;https://realpython.com/what-is-pip/&quot;&gt;What is Pip? A Guide for New Pythonistas&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;pipenv_1&quot;&gt;&lt;code&gt;pipenv&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.pipenv.org/en/latest/&quot;&gt;&lt;code&gt;pipenv&lt;/code&gt;&lt;/a&gt; has most of the same basic operations as &lt;code&gt;pip&lt;/code&gt; but thinks about packages a bit differently. Remember the &lt;code&gt;Pipfile&lt;/code&gt; that &lt;code&gt;pipenv&lt;/code&gt; creates? When you install a package, &lt;code&gt;pipenv&lt;/code&gt; adds that package to &lt;code&gt;Pipfile&lt;/code&gt; and also adds more detailed information to a new &lt;strong&gt;lock file&lt;/strong&gt; called &lt;code&gt;Pipfile.lock&lt;/code&gt;. Lock files act as a snapshot of the precise set of packages installed, including direct dependencies as well as their sub-dependencies.&lt;/p&gt;
&lt;p&gt;You can see &lt;code&gt;pipenv&lt;/code&gt; sorting out the package management when you install a package:&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; pipenv install requests
&lt;span class=&quot;go&quot;&gt;Installing requests…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Adding requests to Pipfile&amp;#39;s [packages]…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;✔ Installation Succeeded&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Pipfile.lock (444a6d) out of date, updating to (a65489)…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Locking [dev-packages] dependencies…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Locking [packages] dependencies…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;✔ Success!&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Updated Pipfile.lock (444a6d)!&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Installing dependencies from Pipfile.lock (444a6d)…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 5/5 — 00:00:00&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;pipenv&lt;/code&gt; will use this lock file, if present, to install the same set of packages. You can ensure that you always have the same set of working dependencies in any Python environment you create using this approach.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pipenv&lt;/code&gt; also distinguishes between &lt;strong&gt;development dependencies&lt;/strong&gt; and &lt;strong&gt;production (regular) dependencies&lt;/strong&gt;. You may need some tools during development, such as &lt;a href=&quot;https://github.com/python/black&quot;&gt;&lt;code&gt;black&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;http://flake8.pycqa.org/en/latest/&quot;&gt;&lt;code&gt;flake8&lt;/code&gt;&lt;/a&gt;, that you don&amp;rsquo;t need when you run your application in production. You can specify that a package is for development when you install it:&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; pipenv install --dev flake8
&lt;span class=&quot;go&quot;&gt;Installing flake8…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Adding flake8 to Pipfile&amp;#39;s [dev-packages]…&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;✔ Installation Succeeded&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;pipenv install&lt;/code&gt; (without any arguments) will only install your production packages by default, but you can tell it to install development dependencies as well with &lt;code&gt;pipenv install --dev&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;poetry&quot;&gt;&lt;code&gt;poetry&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://poetry.eustace.io&quot;&gt;&lt;code&gt;poetry&lt;/code&gt;&lt;/a&gt; addresses additional facets of package management, including creating and publishing your own packages. After installing &lt;code&gt;poetry&lt;/code&gt;, you can use it to create a new project:&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; poetry new myproj
&lt;span class=&quot;go&quot;&gt;Created package myproj in myproj&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ls myproj/
&lt;span class=&quot;go&quot;&gt;README.rst    myproj    pyproject.toml    tests&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Similarly to how &lt;code&gt;pipenv&lt;/code&gt; creates the &lt;code&gt;Pipfile&lt;/code&gt;, &lt;code&gt;poetry&lt;/code&gt; creates a &lt;code&gt;pyproject.toml&lt;/code&gt; file. This &lt;a href=&quot;https://www.python.org/dev/peps/pep-0518/#file-format&quot;&gt;recent standard&lt;/a&gt; contains metadata about the project as well as dependency versions:&lt;/p&gt;
&lt;div class=&quot;highlight ini&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;[tool.poetry]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;myproj&amp;quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;0.1.0&amp;quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;description&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;na&quot;&gt;authors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[&amp;quot;Dane Hillard &amp;lt;github@danehillard.com&amp;gt;&amp;quot;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;[tool.poetry.dependencies]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;^3.7&amp;quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;[tool.poetry.dev-dependencies]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;pytest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;^3.0&amp;quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;[build-system]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[&amp;quot;poetry&amp;gt;=0.12&amp;quot;]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;build-backend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;poetry.masonry.api&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can install packages with &lt;code&gt;poetry add&lt;/code&gt; (or as development dependencies with &lt;code&gt;poetry add --dev&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; poetry add requests
&lt;span class=&quot;go&quot;&gt;Using version ^2.22 for requests&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Updating dependencies&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Resolving dependencies... (0.2s)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Writing lock file&lt;/span&gt;


&lt;span class=&quot;go&quot;&gt;Package operations: 5 installs, 0 updates, 0 removals&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;  - Installing certifi (2019.6.16)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  - Installing chardet (3.0.4)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  - Installing idna (2.8)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  - Installing urllib3 (1.25.3)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  - Installing requests (2.22.0)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;poetry&lt;/code&gt; also maintains a lock file, and it has a benefit over &lt;code&gt;pipenv&lt;/code&gt; because it keeps track of which packages are subdependencies. As a result, you can uninstall &lt;code&gt;requests&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; its dependencies with &lt;code&gt;poetry remove requests&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;conda_2&quot;&gt;&lt;code&gt;conda&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;With &lt;code&gt;conda&lt;/code&gt;, you can use &lt;code&gt;pip&lt;/code&gt; to install packages as usual, but you can also use &lt;code&gt;conda install&lt;/code&gt; to install packages from different &lt;strong&gt;channels &lt;/strong&gt;, which are collections of packages provided by Anaconda or other providers. To install &lt;code&gt;requests&lt;/code&gt; from the &lt;code&gt;conda-forge&lt;/code&gt; channel, you can run &lt;code&gt;conda install -c conda-forge requests&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Learn more about package management in &lt;code&gt;conda&lt;/code&gt; in &lt;a href=&quot;https://realpython.com/python-windows-machine-learning-setup/&quot;&gt;Setting Up Python for Machine Learning on Windows&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;python-interpreters&quot;&gt;Python Interpreters&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re interested in further customization of your Python environment, you can choose the command line experience you have when interacting with Python. The Python interpreter provides a &lt;strong&gt;read-eval-print loop&lt;/strong&gt; (REPL), which is what comes up when you type &lt;code&gt;python&lt;/code&gt; with no arguments in your shell:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;Python 3.7.3 (default, Jun 17 2019, 14:09:05)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[Clang 10.0.1 (clang-1001.0.46.4)] on darwin&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&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;2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The REPL &lt;strong&gt;reads&lt;/strong&gt; what you type, &lt;strong&gt;evaluates&lt;/strong&gt; it as Python code, and &lt;strong&gt;prints&lt;/strong&gt; the result. Then it waits to do it all over again. This is about as much as the default Python REPL provides, which is sufficient for a good portion of typical work.&lt;/p&gt;
&lt;h3 id=&quot;ipython&quot;&gt;IPython&lt;/h3&gt;
&lt;p&gt;Like Anaconda, &lt;a href=&quot;https://ipython.org/&quot;&gt;IPython&lt;/a&gt; is a suite of tools supporting more than just Python, but one of its main features is an alternative Python REPL. IPython&amp;rsquo;s REPL numbers each command and explicitly labels each command&amp;rsquo;s input and output. After installing IPython (&lt;code&gt;python -m pip install ipython&lt;/code&gt;), you can run the &lt;code&gt;ipython&lt;/code&gt; command in place of the &lt;code&gt;python&lt;/code&gt; command to use the IPython REPL:&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;Python 3.7.3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Type &amp;#39;copyright&amp;#39;, &amp;#39;credits&amp;#39; or &amp;#39;license&amp;#39; for more information&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;IPython 6.0.0.dev -- An enhanced Interactive Python. Type &amp;#39;?&amp;#39; for help.&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [1]: &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;2&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[1]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;4&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;Out[2]: &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;Hello!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;IPython also supports &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-tab&quot;&gt;Tab&lt;/kbd&gt;&lt;/span&gt; completion, more powerful help features, and strong integration with other tooling such as &lt;a href=&quot;https://matplotlib.org/&quot;&gt;&lt;code&gt;matplotlib&lt;/code&gt;&lt;/a&gt; for graphing. IPython provided the foundation for &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter&lt;/a&gt;, and both have been used extensively in the data science community because of their integration with other tools.&lt;/p&gt;
&lt;p&gt;The IPython REPL is &lt;a href=&quot;https://ipython.readthedocs.io/en/stable/config/intro.html&quot;&gt;highly configurable&lt;/a&gt; too, so while it falls just shy of being a full development environment, it can still be a boon to your productivity. Its built-in and customizable &lt;a href=&quot;https://ipython.org/ipython-doc/3/interactive/tutorial.html#magic-functions&quot;&gt;magic commands&lt;/a&gt; are worth checking out.&lt;/p&gt;
&lt;h3 id=&quot;bpython&quot;&gt;&lt;code&gt;bpython&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://bpython-interpreter.org&quot;&gt;&lt;code&gt;bpython&lt;/code&gt;&lt;/a&gt; is another alternative REPL that provides inline syntax highlighting, tab completion, and even auto-suggestions as you type. It provides quite a few of the quick benefits of IPython without altering the interface much. Without the weight of the integrations and so on, &lt;code&gt;bpython&lt;/code&gt; might be good to add to your repertoire for a while to see how it improves your use of the REPL.&lt;/p&gt;
&lt;h2 id=&quot;text-editors&quot;&gt;Text Editors&lt;/h2&gt;
&lt;p&gt;You spend a third of your life sleeping, so it makes sense to invest in a great bed. As a developer, you spend a great deal of your time reading and writing code, so it follows that you should invest time in setting up your Python environment&amp;rsquo;s text editor just the way you like it.&lt;/p&gt;
&lt;p&gt;Each editor offers a different set of key bindings and model for manipulating text. Some require a mouse to interact with them effectively, whereas others can be controlled with only the keyboard. Some people consider their choice of text editor and customizations some of the most personal decisions they make!&lt;/p&gt;
&lt;p&gt;There are so many options to choose from in this arena, so I won&amp;rsquo;t attempt to cover it in detail here. Check out &lt;a href=&quot;https://realpython.com/python-ides-code-editors-guide/&quot;&gt;Python IDEs and Code Editors (Guide)&lt;/a&gt; for a broad overview. A good strategy is to find a simple, small text editor for quick changes and a full-featured IDE for more involved work. &lt;a href=&quot;https://www.vim.org/&quot;&gt;Vim&lt;/a&gt; and &lt;a href=&quot;https://www.jetbrains.com/pycharm/&quot;&gt;PyCharm&lt;/a&gt;, respectively, are my editors of choice.&lt;/p&gt;
&lt;h2 id=&quot;python-environment-tips-and-tricks&quot;&gt;Python Environment Tips and Tricks&lt;/h2&gt;
&lt;p&gt;Once you&amp;rsquo;ve made the big decisions about your Python environment, the rest of the road is paved with little tweaks to make your life a little easier. These tweaks each save minutes or seconds alone, but they collectively save you hours of time.&lt;/p&gt;
&lt;p&gt;Making a certain activity easier reduces your cognitive load so you can focus on the task at hand instead of the logistics surrounding it. If you notice yourself performing an action over and over, then consider automating it. Use &lt;a href=&quot;https://xkcd.com/1205/&quot;&gt;this wonderful chart&lt;/a&gt; from XKCD to determine if it&amp;rsquo;s worth automating a particular task.&lt;/p&gt;
&lt;p&gt;Here are a few final tips.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Know your current virtual environment&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As mentioned earlier, it&amp;rsquo;s a great idea to display the active Python version or virtual environment in your command prompt. Most tools will do this for you, but if not (or if you want to customize the prompt), the value is usually contained in the &lt;code&gt;VIRTUAL_ENV&lt;/code&gt; environment variable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disable unnecessary, temporary files&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Have you ever noticed &lt;code&gt;*.pyc&lt;/code&gt; files all over your project directories? These files are pre-compiled Python bytecode&amp;mdash;they help Python start your application faster. In production, these are a great idea because they&amp;rsquo;ll give you some performance gain. During local development, however, they&amp;rsquo;re rarely useful. Set &lt;code&gt;PYTHONDONTWRITEBYTECODE=1&lt;/code&gt; to disable this behavior. If you find use cases for them later, then you can easily remove this from your Python environment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Customize your Python interpreter&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can affect how the REPL behaves using a &lt;strong&gt;startup file&lt;/strong&gt;. Python will read this startup file and execute the code it contains before entering the REPL. Set the &lt;code&gt;PYTHONSTARTUP&lt;/code&gt; environment variable to the path of your startup file. (Mine&amp;rsquo;s at &lt;code&gt;~/.pystartup&lt;/code&gt;.) If you&amp;rsquo;d like to hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-arrow-up&quot;&gt;Up&lt;/kbd&gt;&lt;/span&gt; for command history and &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-tab&quot;&gt;Tab&lt;/kbd&gt;&lt;/span&gt; for completion like your shell provides, then give &lt;a href=&quot;https://github.com/daneah/dotfiles/blob/master/source/pystartup&quot;&gt;this startup file&lt;/a&gt; a try.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You learned about many facets of the typical Python environment. Armed with this knowledge, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Choose a terminal with the aesthetics and enhanced features you like&lt;/li&gt;
&lt;li&gt;Choose a shell with as many (or as few) customization options as you need&lt;/li&gt;
&lt;li&gt;Manage multiple versions of Python on your system&lt;/li&gt;
&lt;li&gt;Manage multiple projects that use a single version of Python, using virtual Python environments&lt;/li&gt;
&lt;li&gt;Install packages in your virtual environments&lt;/li&gt;
&lt;li&gt;Choose a REPL that suits your interactive coding needs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you&amp;rsquo;ve got your Python environment just so, I hope you&amp;rsquo;ll share screenshots, screencasts, or blog posts about your perfect setup ✨&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>Traditional Face Detection With Python</title>
      <id>https://realpython.com/courses/traditional-face-detection-python/</id>
      <link href="https://realpython.com/courses/traditional-face-detection-python/"/>
      <updated>2019-08-13T14:00:00+00:00</updated>
      <summary>In this course on face detection with Python, you&#39;ll learn about a historically important algorithm for object detection that can be successfully applied to finding the location of a human face within an image.</summary>
      <content type="html">
        &lt;p&gt;&lt;strong&gt;Computer vision&lt;/strong&gt; is an exciting and growing field. There are tons of interesting problems to solve! One of them is face detection: the ability of a computer to recognize that a photograph contains a human face, and tell you where it is located. In this course, you&amp;rsquo;ll learn about &lt;strong&gt;face detection&lt;/strong&gt; with Python.&lt;/p&gt;
&lt;p&gt;To detect any object in an image, it is necessary to understand how images are represented inside a computer, and how that object differs &lt;em&gt;visually&lt;/em&gt; from any other object.&lt;/p&gt;
&lt;p&gt;Once that is done, the process of scanning an image and looking for those visual cues needs to be automated and optimized. All these steps come together to form a fast and reliable computer vision algorithm.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this course, you&amp;rsquo;ll learn:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What face detection is&lt;/li&gt;
&lt;li&gt;How computers understand features in images&lt;/li&gt;
&lt;li&gt;How to quickly analyze many different features to reach a decision&lt;/li&gt;
&lt;li&gt;How to use a minimal Python solution for detecting human faces in images&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>Your Guide to the Python Print Function</title>
      <id>https://realpython.com/python-print/</id>
      <link href="https://realpython.com/python-print/"/>
      <updated>2019-08-12T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn about the print() function in Python and discover some of its lesser-known features. Avoid common mistakes, take your &quot;hello world&quot; to the next level, and know when to use a better alternative.</summary>
      <content type="html">
        &lt;p&gt;If you&amp;rsquo;re like most Python users, including me, then you probably started your Python journey by learning about &lt;code&gt;print()&lt;/code&gt;. It helped you write your very own &lt;code&gt;hello world&lt;/code&gt; one-liner. You can use it to display formatted messages onto the screen and perhaps find some bugs. But if you think that&amp;rsquo;s all there is to know about Python&amp;rsquo;s &lt;code&gt;print()&lt;/code&gt; function, then you&amp;rsquo;re missing out on a lot!&lt;/p&gt;
&lt;p&gt;Keep reading to take full advantage of this seemingly boring and unappreciated little function. This tutorial will get you up to speed with using Python &lt;code&gt;print()&lt;/code&gt; effectively. However, prepare for a deep dive as you go through the sections. You may be surprised how much &lt;code&gt;print()&lt;/code&gt; has to offer!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this tutorial, you&amp;rsquo;ll know how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid common mistakes with Python&amp;rsquo;s &lt;code&gt;print()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Deal with newlines, character encodings, and buffering&lt;/li&gt;
&lt;li&gt;Write text to files&lt;/li&gt;
&lt;li&gt;Mock &lt;code&gt;print()&lt;/code&gt; in unit tests&lt;/li&gt;
&lt;li&gt;Build advanced user interfaces in the terminal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;rsquo;re a complete beginner, then you&amp;rsquo;ll benefit most from reading the first part of this tutorial, which illustrates the essentials of printing in Python. Otherwise, feel free to skip that part and jump around as you see fit.&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;print()&lt;/code&gt; was a major addition to Python 3, in which it replaced the old &lt;code&gt;print&lt;/code&gt; statement available in Python 2.&lt;/p&gt;
&lt;p&gt;There were a number of good reasons for that, as you&amp;rsquo;ll see shortly. Although this tutorial focuses on Python 3, it does show the old way of printing in Python for reference.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-cheat-sheet-experiment&quot; data-focus=&quot;false&quot;&gt;Click here to get our free Python Cheat Sheet&lt;/a&gt; that shows you the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;printing-in-a-nutshell&quot;&gt;Printing in a Nutshell&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s jump in by looking at a few real-life examples of printing in Python. By the end of this section, you&amp;rsquo;ll know every possible way of calling &lt;code&gt;print()&lt;/code&gt;. Or, in programmer lingo, you&amp;rsquo;d say you&amp;rsquo;ll be familiar with the &lt;strong&gt;function signature&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;calling-print&quot;&gt;Calling Print&lt;/h3&gt;
&lt;p&gt;The simplest example of using Python &lt;code&gt;print()&lt;/code&gt; requires just a few keystrokes:&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;You don&amp;rsquo;t pass any arguments, but you still need to put empty parentheses at the end, which tell Python to actually &lt;a href=&quot;https://realpython.com/lessons/example-function/&quot;&gt;execute the function&lt;/a&gt; rather than just refer to it by name.&lt;/p&gt;
&lt;p&gt;This will produce an invisible newline character, which in turn will cause a blank line to appear on your screen. You can call &lt;code&gt;print()&lt;/code&gt; multiple times like this to add vertical space. It&amp;rsquo;s just as if you were hitting &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; on your keyboard in a word processor.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card5787b1&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;#collapse5787b1&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse5787b1&quot;&gt;Newline Character&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse5787b1&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse5787b1&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse5787b1&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card5787b1&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;A &lt;strong&gt;newline character&lt;/strong&gt; is a special control character used to indicate the end of a line (EOL). It usually doesn&amp;rsquo;t have a visible representation on the screen, but some text editors can display such non-printable characters with little graphics.&lt;/p&gt;
&lt;p&gt;The word &amp;ldquo;character&amp;rdquo; is somewhat of a misnomer in this case, because a newline is often more than one character long. For example, the Windows operating system, as well as the HTTP protocol, represent newlines with a pair of characters. Sometimes you need to take those differences into account to design truly portable programs.&lt;/p&gt;
&lt;p&gt;To find out what constitutes a newline in your operating system, use Python&amp;rsquo;s built-in &lt;code&gt;os&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;This will immediately tell you that &lt;strong&gt;Windows&lt;/strong&gt; and &lt;strong&gt;DOS&lt;/strong&gt; represent the newline as a sequence of &lt;code&gt;\r&lt;/code&gt; followed by &lt;code&gt;\n&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;os&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linesep&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;\r\n&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On &lt;strong&gt;Unix&lt;/strong&gt;, &lt;strong&gt;Linux&lt;/strong&gt;, and recent versions of &lt;strong&gt;macOS&lt;/strong&gt;, it&amp;rsquo;s a single &lt;code&gt;\n&lt;/code&gt; character:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linesep&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The classic &lt;strong&gt;Mac OS X&lt;/strong&gt;, however, sticks to its own &amp;ldquo;think different&amp;rdquo; philosophy by choosing yet another representation:&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;os&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linesep&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;\r&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how these characters appear in string literals. They use special syntax with a preceding backslash (&lt;code&gt;\&lt;/code&gt;) to denote the start of an &lt;strong&gt;escape character sequence&lt;/strong&gt;. Such sequences allow for representing control characters, which would be otherwise invisible on screen.&lt;/p&gt;
&lt;p&gt;Most programming languages come with a predefined set of escape sequences for special characters such as these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;\\&lt;/code&gt;:&lt;/strong&gt; backslash&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;\b&lt;/code&gt;:&lt;/strong&gt; backspace&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;\t&lt;/code&gt;:&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;\r&lt;/code&gt;:&lt;/strong&gt; carriage return (CR)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;\n&lt;/code&gt;:&lt;/strong&gt; newline, also known as line feed (LF)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last two are reminiscent of mechanical typewriters, which required two separate commands to insert a newline. The first command would move the carriage back to the beginning of the current line, while the second one would advance the roll to the next line.&lt;/p&gt;
&lt;p&gt;By comparing the corresponding &lt;strong&gt;ASCII character codes&lt;/strong&gt;, you&amp;rsquo;ll see that putting a backslash in front of a character changes its meaning completely. However, not all characters allow for this&amp;ndash;only the special ones.&lt;/p&gt;
&lt;p&gt;To compare ASCII character codes, you may want to use the built-in &lt;code&gt;ord()&lt;/code&gt; 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;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;114&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Keep in mind that, in order to form a correct escape sequence, there must be no space between the backslash character and a letter!&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;As you just saw, calling &lt;code&gt;print()&lt;/code&gt; without arguments results in a &lt;strong&gt;blank line&lt;/strong&gt;, which is a line comprised solely of the newline character. Don&amp;rsquo;t confuse this with an &lt;strong&gt;empty line&lt;/strong&gt;, which doesn&amp;rsquo;t contain any characters at all, not even the newline!&lt;/p&gt;
&lt;p&gt;You can use Python&amp;rsquo;s &lt;a href=&quot;https://realpython.com/python-strings/&quot;&gt;string&lt;/a&gt; literals to visualize these two:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Blank line&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Empty line&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first one is one character long, whereas the second one has no content.&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; To remove the newline character from a string in Python, use its &lt;code&gt;.rstrip()&lt;/code&gt; method, 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;s1&quot;&gt;&amp;#39;A line of text.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rstrip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;A line of text.&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This strips any trailing whitespace from the right edge of the string of characters.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In a more common scenario, you&amp;rsquo;d want to communicate some message to the end user. There are a few ways to achieve this.&lt;/p&gt;
&lt;p&gt;First, you may pass a string literal directly to &lt;code&gt;print()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait while the program is loading...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will print the message verbatim onto the screen.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardf395ab&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;#collapsef395ab&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef395ab&quot;&gt;String Literals&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef395ab&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef395ab&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsef395ab&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardf395ab&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;strong&gt;String literals&lt;/strong&gt; in Python can be enclosed either in single quotes (&lt;code&gt;&#39;&lt;/code&gt;) or  double quotes (&lt;code&gt;&quot;&lt;/code&gt;). According to the official &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/#string-quotes&quot;&gt;PEP 8&lt;/a&gt; style guide, you should just pick one and keep using it consistently. There&amp;rsquo;s no difference, unless you need to nest one in another.&lt;/p&gt;
&lt;p&gt;For example, you can&amp;rsquo;t use double quotes for the literal and also include double quotes inside of it, because that&amp;rsquo;s ambiguous for the Python interpreter:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My favorite book is &amp;quot;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tricks&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Wrong!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What you want to do is enclose the text, which contains double quotes, within single quotes:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;My favorite book is &amp;quot;Python Tricks&amp;quot;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The same trick would work the other way around:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My favorite book is &amp;#39;Python Tricks&amp;#39;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, you could use escape character sequences mentioned earlier, to make Python treat those internal double quotes literally as part of the string literal:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My favorite book is &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Python Tricks&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Escaping is fine and dandy, but it can sometimes get in the way. Specifically, when you need your string to contain relatively many backslash characters in literal form.&lt;/p&gt;
&lt;p&gt;One classic example is a file path on Windows:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;C:\Users\jdoe&amp;#39;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Wrong!&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&amp;#39;C:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Users&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;jdoe&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how each backslash character needs to be escaped with yet another backslash.&lt;/p&gt;
&lt;p&gt;This is even more prominent with regular expressions, which quickly get convoluted due to the heavy use of special characters:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;w:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;(?:(?:(?:[^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;]+)?|(?:[^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;]+)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;[^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;]+)*)$&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Fortunately, you can turn off character escaping entirely with the help of raw-string literals. Simply prepend an &lt;code&gt;r&lt;/code&gt; or &lt;code&gt;R&lt;/code&gt; before the opening quote, and now you end up with 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;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;C:\Users\jdoe&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;^\w:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;(?:(?:(?:[^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;]+)?|(?:[^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;]+)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;[^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;]+)*)$&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s much better, isn&amp;rsquo;t it?&lt;/p&gt;
&lt;p&gt;There are a few more prefixes that give special meaning to string literals in Python, but you won&amp;rsquo;t get into them here.&lt;/p&gt;
&lt;p&gt;Lastly, you can define multi-line string literals by enclosing them between &lt;code&gt;&#39;&#39;&#39;&lt;/code&gt; or &lt;code&gt;&quot;&quot;&quot;&lt;/code&gt;, which are often used as &lt;strong&gt;docstrings&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;This is an example&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;of a multi-line string&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;in Python.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To prevent an initial newline, simply put the text right after the opening &lt;code&gt;&quot;&quot;&quot;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;This is an example&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;of a multi-line string&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;in Python.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also use a backslash to get rid of the newline:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;\&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;This is an example&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;of a multi-line string&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;in Python.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt; 
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To remove indentation from a multi-line string, you might take advantage of the built-in &lt;code&gt;textwrap&lt;/code&gt; module:&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;textwrap&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;    This is an example&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;    of a multi-line string&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;    in Python.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    This is an example&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    of a multi-line string&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    in Python.&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;textwrap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dedent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&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;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;This is an example&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;of a multi-line string&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;in Python.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will take care of unindenting paragraphs for you. There are also a few other useful functions in &lt;code&gt;textwrap&lt;/code&gt; for text alignment you&amp;rsquo;d find in a word processor.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;Secondly, you could extract that message into its own variable with a meaningful name to enhance readability and promote code reuse:&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;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait while the program is loading...&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lastly, you could pass an expression, like &lt;a href=&quot;https://realpython.com/lessons/concatenating-joining-strings-python/&quot;&gt;string concatenation&lt;/a&gt;, to be evaluated before printing the result:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&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;s1&quot;&gt;&amp;#39;Hello, &amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getlogin&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;s1&quot;&gt;&amp;#39;! How are you?&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Hello, jdoe! How are you?&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In fact, there are a dozen ways to format messages in Python. I highly encourage you to take a look at &lt;a href=&quot;https://realpython.com/python-f-strings/&quot;&gt;f-strings&lt;/a&gt;, introduced in Python 3.6, because they offer the most concise syntax of them all:&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;os&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello, {os.getlogin()}! How are you?&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Moreover, f-strings will prevent you from making a common mistake, which is forgetting to type cast concatenated operands. Python is a strongly typed language, which means it won&amp;rsquo;t allow you to do 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;s1&quot;&gt;&amp;#39;My age is &amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;input&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;My age is &amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;can only concatenate str (not &amp;quot;int&amp;quot;) to str&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s wrong because adding numbers to strings doesn&amp;rsquo;t make sense. You need to explicitly convert the number to string first, in order to join them together:&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;s1&quot;&gt;&amp;#39;My age is &amp;#39;&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;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;My age is 42&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unless you &lt;a href=&quot;https://realpython.com/courses/python-exceptions-101/&quot;&gt;handle such errors&lt;/a&gt; yourself, the Python interpreter will let you know about a problem by showing a &lt;a href=&quot;https://realpython.com/python-traceback/&quot;&gt;traceback&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;str()&lt;/code&gt; is a global built-in function that converts an object into its string representation.&lt;/p&gt;
&lt;p&gt;You can call it directly on any object, for example, a number:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;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;&amp;#39;3.14&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Built-in data types have a predefined string representation out of the box, but later in this article, you&amp;rsquo;ll find out how to provide one for your custom classes.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As with any function, it doesn&amp;rsquo;t matter whether you pass a literal, a variable, or an expression. Unlike many other functions, however, &lt;code&gt;print()&lt;/code&gt; will accept anything regardless of its type.&lt;/p&gt;
&lt;p&gt;So far, you only looked at the string, but how about other data types? Let&amp;rsquo;s try literals of different built-in types and see what comes out:&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;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;# &amp;lt;class &amp;#39;int&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;42&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;mf&quot;&gt;3.14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                          &lt;span class=&quot;c1&quot;&gt;# &amp;lt;class &amp;#39;float&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3.14&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;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# &amp;lt;class &amp;#39;complex&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(1+2j)&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;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                          &lt;span class=&quot;c1&quot;&gt;# &amp;lt;class &amp;#39;bool&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;# &amp;lt;class &amp;#39;list&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 2, 3]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;# &amp;lt;class &amp;#39;tuple&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(1, 2, 3)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;red&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;green&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# &amp;lt;class &amp;#39;set&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;red&amp;#39;, &amp;#39;green&amp;#39;, &amp;#39;blue&amp;#39;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;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;name&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Alice&amp;#39;&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;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &amp;lt;class &amp;#39;dict&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;name&amp;#39;: &amp;#39;Alice&amp;#39;, &amp;#39;age&amp;#39;: 42}&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;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;c1&quot;&gt;# &amp;lt;class &amp;#39;str&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;hello&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Watch out for the &lt;code&gt;None&lt;/code&gt; constant, though. Despite being used to indicate an absence of a value, it will show up as &lt;code&gt;&#39;None&#39;&lt;/code&gt; rather than an empty 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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;None&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;How does &lt;code&gt;print()&lt;/code&gt; know how to work with all these different types? Well, the short answer is that it doesn&amp;rsquo;t. It implicitly calls &lt;code&gt;str()&lt;/code&gt; behind the scenes to type cast any object into a string. Afterward, it treats strings in a uniform way.&lt;/p&gt;
&lt;p&gt;Later in this tutorial, you&amp;rsquo;ll learn how to use this mechanism for printing custom data types such as your classes.&lt;/p&gt;
&lt;p&gt;Okay, you&amp;rsquo;re now able to call &lt;code&gt;print()&lt;/code&gt; with a single argument or without any arguments. You know how to print fixed or formatted messages onto the screen. The next subsection will expand on message formatting a little bit.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card09ba8e&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;#collapse09ba8e&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse09ba8e&quot;&gt;Syntax in Python 2&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse09ba8e&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse09ba8e&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse09ba8e&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card09ba8e&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;To achieve the same result in the previous language generation, you&amp;rsquo;d normally want to drop the parentheses enclosing the text:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait...&amp;#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;! How are you?&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getlogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;. Your age is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;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;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s because &lt;code&gt;print&lt;/code&gt; wasn&amp;rsquo;t a function back then, as you&amp;rsquo;ll see in the &lt;a href=&quot;#understanding-python-print&quot;&gt;next section&lt;/a&gt;. Note, however, that in some cases parentheses in Python are redundant. It wouldn&amp;rsquo;t harm to include them as they&amp;rsquo;d just get ignored. Does that mean you should be using the &lt;code&gt;print&lt;/code&gt; statement as if it were a function? Absolutely not!&lt;/p&gt;
&lt;p&gt;For example, parentheses enclosing a single expression or a literal are optional. Both instructions produce the same result in Python 2:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 2&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;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait...&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Please wait...&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Please wait...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Round brackets are actually part of the expression rather than the &lt;code&gt;print&lt;/code&gt; statement. If your expression happens to contain only one item, then it&amp;rsquo;s as if you didn&amp;rsquo;t include the brackets at all.&lt;/p&gt;
&lt;p&gt;On the other hand, putting parentheses around multiple items forms a &lt;a href=&quot;https://realpython.com/python-lists-tuples/#python-tuples&quot;&gt;tuple&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 2&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;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;My name is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My name is John&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;My name is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;My name is&amp;#39;, &amp;#39;John&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is a known source of confusion. In fact, you&amp;rsquo;d also get a tuple by appending a trailing comma to the only item surrounded by 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;c1&quot;&gt;# Python 2&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Please wait...&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Notice the comma&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;Please wait...&amp;#39;,)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The bottom line is that you shouldn&amp;rsquo;t call &lt;code&gt;print&lt;/code&gt; with brackets in Python 2. Although, to be completely accurate, you can work around this with the help of a &lt;code&gt;__future__&lt;/code&gt; import, which you&amp;rsquo;ll read more about in the relevant section.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h3 id=&quot;separating-multiple-arguments&quot;&gt;Separating Multiple Arguments&lt;/h3&gt;
&lt;p&gt;You saw &lt;code&gt;print()&lt;/code&gt; called without any arguments to produce a blank line and then called with a single argument to display either a fixed or a formatted message.&lt;/p&gt;
&lt;p&gt;However, it turns out that this function can accept any number of &lt;strong&gt;positional arguments&lt;/strong&gt;, including zero, one, or more arguments. That&amp;rsquo;s very handy in a common case of message formatting, where you&amp;rsquo;d want to join a few elements together.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card9620b8&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;#collapse9620b8&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse9620b8&quot;&gt;Positional Arguments&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse9620b8&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse9620b8&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse9620b8&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card9620b8&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;Arguments can be passed to a function in one of several ways. One way is by explicitly naming the arguments when you&amp;rsquo;re calling the function, 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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;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;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&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;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&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;0.75&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since arguments can be uniquely identified by name, their order doesn&amp;rsquo;t matter. Swapping them out will still give the same result:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&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;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;go&quot;&gt;0.75&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Conversely, arguments passed without names are identified by their position. That&amp;rsquo;s why &lt;strong&gt;positional arguments&lt;/strong&gt; need to follow strictly the order imposed by the function signature:&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;div&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;go&quot;&gt;0.75&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1.3333333333333333&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;print()&lt;/code&gt; allows an &lt;a href=&quot;https://docs.python.org/dev/tutorial/controlflow.html#arbitrary-argument-lists&quot;&gt;arbitrary number of positional arguments&lt;/a&gt; thanks to the &lt;code&gt;*args&lt;/code&gt; parameter.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at this 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&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;s1&quot;&gt;&amp;#39;My name is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getlogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;and I am&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My name is jdoe and I am 42&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;print()&lt;/code&gt; concatenated all four arguments passed to it, and it inserted a single space between them so that you didn&amp;rsquo;t end up with a squashed message like &lt;code&gt;&#39;My name isjdoeand I am42&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Notice that it also took care of proper type casting by implicitly calling &lt;code&gt;str()&lt;/code&gt; on each argument before joining them together. If you recall from the previous subsection, a naïve concatenation may easily result in an error due to incompatible types:&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;s1&quot;&gt;&amp;#39;My age is: &amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;input&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;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;My age is: &amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;can only concatenate str (not &amp;quot;int&amp;quot;) to str&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Apart from accepting a variable number of positional arguments, &lt;code&gt;print()&lt;/code&gt; defines four named or &lt;strong&gt;keyword arguments&lt;/strong&gt;, which are optional since they all have default values. You can view their brief documentation by calling &lt;code&gt;help(print)&lt;/code&gt; from the interactive interpreter.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s focus on &lt;code&gt;sep&lt;/code&gt; just for now. It stands for &lt;strong&gt;separator&lt;/strong&gt; and is assigned a single space (&lt;code&gt;&#39; &#39;&lt;/code&gt;) by default. It determines the value to join elements with.&lt;/p&gt;
&lt;p&gt;It has to be either a string or &lt;code&gt;None&lt;/code&gt;, but the latter has the same effect as the default space:&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;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;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;n&quot;&gt;sep&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;go&quot;&gt;hello world&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;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;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;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;hello world&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;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;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;go&quot;&gt;hello world&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you wanted to suppress the separator completely, you&amp;rsquo;d have to pass an empty string (&lt;code&gt;&#39;&#39;&lt;/code&gt;) instead:&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;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;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;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;helloworld&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You may want &lt;code&gt;print()&lt;/code&gt; to join its arguments as separate lines. In that case, simply pass the escaped newline character described earlier:&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;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;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;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;hello&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;world&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A more useful example of the &lt;code&gt;sep&lt;/code&gt; parameter would be printing something like file paths:&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;s1&quot;&gt;&amp;#39;home&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;documents&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;home/user/documents&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Remember that the separator comes between the elements, not around them, so you need to account for that in one way or another:&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;s1&quot;&gt;&amp;#39;/home&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;documents&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/home/user/documents&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;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;home&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;documents&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/home/user/documents&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Specifically, you can insert a slash character (&lt;code&gt;/&lt;/code&gt;) into the first positional argument, or use an empty string as the first argument to enforce the leading slash.&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; Be careful about joining elements of a list or tuple.&lt;/p&gt;
&lt;p&gt;Doing it manually will result in a well-known &lt;code&gt;TypeError&lt;/code&gt; if at least one of the elements isn&amp;rsquo;t a 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;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; &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;jdoe is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;years old&amp;#39;&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;input&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;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;,&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;jdoe is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;years old&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;sequence item 1: expected str instance, int found&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s safer to just unpack the sequence with the star operator (&lt;code&gt;*&lt;/code&gt;) and let &lt;code&gt;print()&lt;/code&gt; handle type casting:&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;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;jdoe is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;years old&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;jdoe is 42 years old&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unpacking is effectively the same as calling &lt;code&gt;print()&lt;/code&gt; with individual elements of the list.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;One more interesting example could be exporting data to a &lt;a href=&quot;https://realpython.com/courses/reading-and-writing-csv-files/&quot;&gt;comma-separated values&lt;/a&gt; (CSV) 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;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;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;Python Tricks&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Dan Bader&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1,Python Tricks,Dan Bader&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This wouldn&amp;rsquo;t handle edge cases such as escaping commas correctly, but for simple use cases, it should do. The line above would show up in your terminal window. In order to save it to a file, you&amp;rsquo;d have to redirect the output. Later in this section, you&amp;rsquo;ll see how to use &lt;code&gt;print()&lt;/code&gt; to write text to files straight from Python.&lt;/p&gt;
&lt;p&gt;Finally, the &lt;code&gt;sep&lt;/code&gt; parameter isn&amp;rsquo;t constrained to a single character only. You can join elements with strings of any length:&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;s1&quot;&gt;&amp;#39;node&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;child&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;child&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39; -&amp;gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;node -&amp;gt; child -&amp;gt; child&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the upcoming subsections, you&amp;rsquo;ll explore the remaining keyword arguments of the &lt;code&gt;print()&lt;/code&gt; function.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardab50a5&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;#collapseab50a5&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapseab50a5&quot;&gt;Syntax in Python 2&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapseab50a5&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapseab50a5&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapseab50a5&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardab50a5&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;To print multiple elements in Python 2, you must drop the parentheses around them, just like before:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 2&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;os&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;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;My name is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getlogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;and I am&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My name is jdoe and I am 42&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you kept them, on the other hand, you&amp;rsquo;d be passing a single tuple element to the &lt;code&gt;print&lt;/code&gt; statement:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 2&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;os&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;My name is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getlogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;and I am&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;My name is&amp;#39;, &amp;#39;jdoe&amp;#39;, &amp;#39;and I am&amp;#39;, 42)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Moreover, there&amp;rsquo;s no way of altering the default separator of joined elements in Python 2, so one workaround is to use string interpolation like so:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 2&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;os&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;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;My name is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; and I am &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getlogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My name is jdoe and I am 42&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That was the default way of formatting strings until the &lt;code&gt;.format()&lt;/code&gt; method got backported from Python 3.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h3 id=&quot;preventing-line-breaks&quot;&gt;Preventing Line Breaks&lt;/h3&gt;
&lt;p&gt;Sometimes you don&amp;rsquo;t want to end your message with a trailing newline so that subsequent calls to &lt;code&gt;print()&lt;/code&gt; will continue on the same line. Classic examples include updating the progress of a long-running operation or prompting the user for input. In the latter case, you want the user to type in the answer on the same line:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Are you sure you want to do this? [y/n] y
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Many programming languages expose functions similar to &lt;code&gt;print()&lt;/code&gt; through their standard libraries, but they let you decide whether to add a newline or not. For example, in Java and C#, you have two distinct functions, while other languages require you to explicitly append &lt;code&gt;\n&lt;/code&gt; at the end of a string literal.&lt;/p&gt;
&lt;p&gt;Here are a few examples of syntax in such languages:&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;Language&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Perl&lt;/td&gt;
&lt;td&gt;&lt;code&gt;print &quot;hello world\n&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;&lt;code&gt;printf(&quot;hello world\n&quot;);&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C++&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::cout &amp;lt;&amp;lt; &quot;hello world&quot; &amp;lt;&amp;lt; std::endl;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;In contrast, Python&amp;rsquo;s &lt;code&gt;print()&lt;/code&gt; function always adds &lt;code&gt;\n&lt;/code&gt; without asking, because that&amp;rsquo;s what you want in most cases. To disable it, you can take advantage of yet another keyword argument, &lt;code&gt;end&lt;/code&gt;, which dictates what to end the line with.&lt;/p&gt;
&lt;p&gt;In terms of semantics, the &lt;code&gt;end&lt;/code&gt; parameter is almost identical to the &lt;code&gt;sep&lt;/code&gt; one that you saw earlier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It must be a string or &lt;code&gt;None&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It can be arbitrarily long.&lt;/li&gt;
&lt;li&gt;It has a default value of &lt;code&gt;&#39;\n&#39;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If equal to &lt;code&gt;None&lt;/code&gt;, it&amp;rsquo;ll have the same effect as the default value.&lt;/li&gt;
&lt;li&gt;If equal to an empty string (&lt;code&gt;&#39;&#39;&lt;/code&gt;), it&amp;rsquo;ll suppress the newline.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you understand what&amp;rsquo;s happening under the hood when you&amp;rsquo;re calling &lt;code&gt;print()&lt;/code&gt; without arguments. Since you don&amp;rsquo;t provide any positional arguments to the function, there&amp;rsquo;s nothing to be joined, and so the default separator isn&amp;rsquo;t used at all. However, the default value of &lt;code&gt;end&lt;/code&gt; still applies, and a blank line shows up.&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 may be wondering why the &lt;code&gt;end&lt;/code&gt; parameter has a fixed default value rather than whatever makes sense on your operating system.&lt;/p&gt;
&lt;p&gt;Well, you don&amp;rsquo;t have to worry about newline representation across different operating systems when printing, because &lt;code&gt;print()&lt;/code&gt; will handle the conversion automatically. Just remember to always use the &lt;code&gt;\n&lt;/code&gt; escape sequence in string literals.&lt;/p&gt;
&lt;p&gt;This is currently the most portable way of printing a newline character in Python:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;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;line1&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;line2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;line3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;line1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;line2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;line3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you were to try to forcefully print a Windows-specific newline character on a Linux machine, for example, you&amp;rsquo;d end up with broken output:&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;s1&quot;&gt;&amp;#39;line1&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;line2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;line3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;go&quot;&gt;line3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the flip side, when you open a file for reading with &lt;code&gt;open()&lt;/code&gt;, you don&amp;rsquo;t need to care about newline representation either. The function will translate any system-specific newline it encounters into a universal &lt;code&gt;&#39;\n&#39;&lt;/code&gt;. At the same time, you have control over how the newlines should be treated both on input and output if you really need that.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To disable the newline, you must specify an empty string through the &lt;code&gt;end&lt;/code&gt; keyword argument:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;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;Checking file integrity...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&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;ok&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Even though these are two separate &lt;code&gt;print()&lt;/code&gt; calls, which can execute a long time apart, you&amp;rsquo;ll eventually see only one line. First, it&amp;rsquo;ll look like this:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Checking file integrity...
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, after the second call to &lt;code&gt;print()&lt;/code&gt;, the same line will appear on the screen as:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Checking file integrity...ok
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As with &lt;code&gt;sep&lt;/code&gt;, you can use &lt;code&gt;end&lt;/code&gt; to join individual pieces into a big blob of text with a custom separator. Instead of joining multiple arguments, however, it&amp;rsquo;ll append text from each function call to the same line:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;The first sentence&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;. &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;The second sentence&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;. &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;The last sentence.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These three instructions will output a single line of text:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;The first sentence. The second sentence. The last sentence.
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can mix the two keyword arguments:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Mercury&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Venus&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Earth&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;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;Mars&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Jupiter&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Saturn&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;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;Uranus&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Neptune&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Pluto&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Not only do you get a single line of text, but all items are separated with a comma:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There&amp;rsquo;s nothing to stop you from using the newline character with some extra padding around it:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Printing in a Nutshell&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&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;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;Calling Print&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&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;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;Separating Multiple Arguments&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&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;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;Preventing Line Breaks&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It would print out the following piece of text:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Printing in a Nutshell
 * Calling Print
 * Separating Multiple Arguments
 * Preventing Line Breaks
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the &lt;code&gt;end&lt;/code&gt; keyword argument will accept arbitrary strings.&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; Looping over lines in a text file preserves their own newline characters, which combined with the &lt;code&gt;print()&lt;/code&gt; function&amp;rsquo;s default behavior will result in a redundant newline character:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.txt&amp;#39;&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;file_object&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;line&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are two newlines after each line of text. You want to strip one of the them, as shown earlier in this article, before printing the line:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rstrip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, you can keep the newline in the content but suppress the one appended by &lt;code&gt;print()&lt;/code&gt; automatically. You&amp;rsquo;d use the &lt;code&gt;end&lt;/code&gt; keyword argument to do that:&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;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.txt&amp;#39;&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;file_object&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;line&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By ending a line with an empty string, you effectively disable one of the newlines.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You&amp;rsquo;re getting more acquainted with printing in Python, but there&amp;rsquo;s still a lot of useful information ahead. In the upcoming subsection, you&amp;rsquo;ll learn how to intercept and redirect the &lt;code&gt;print()&lt;/code&gt; function&amp;rsquo;s output.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card37ad87&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;#collapse37ad87&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse37ad87&quot;&gt;Syntax in Python 2&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse37ad87&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse37ad87&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse37ad87&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card37ad87&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;Preventing a line break in Python 2 requires that you append a trailing comma to the expression:&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;print&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, that&amp;rsquo;s not ideal because it also adds an unwanted space, which would translate to &lt;code&gt;end=&#39; &#39;&lt;/code&gt; instead of &lt;code&gt;end=&#39;&#39;&lt;/code&gt; in Python 3. You can test this with the following code snippet:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;BEFORE&amp;#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&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;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;AFTER&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice there&amp;rsquo;s a space between the words &lt;code&gt;hello&lt;/code&gt; and &lt;code&gt;AFTER&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;BEFORE
hello AFTER
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In order to get the expected result, you&amp;rsquo;d need to use one of the tricks explained later, which is either importing the &lt;code&gt;print()&lt;/code&gt; function from &lt;code&gt;__future__&lt;/code&gt; or falling back to the &lt;code&gt;sys&lt;/code&gt; module:&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;sys&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;BEFORE&amp;#39;&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;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;AFTER&amp;#39;&lt;/span&gt; 
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will print the correct output without extra space:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;BEFORE
helloAFTER
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While using the &lt;code&gt;sys&lt;/code&gt; module gives you control over what gets printed to the standard output, the code becomes a little bit more cluttered.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h3 id=&quot;printing-to-a-file&quot;&gt;Printing to a File&lt;/h3&gt;
&lt;p&gt;Believe it or not, &lt;code&gt;print()&lt;/code&gt; doesn&amp;rsquo;t know how to turn messages into text on your screen, and frankly it doesn&amp;rsquo;t need to. That&amp;rsquo;s a job for lower-level layers of code, which understand bytes and know how to push them around.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;print()&lt;/code&gt; is an abstraction over these layers, providing a convenient interface that merely delegates the actual printing to a stream or &lt;strong&gt;file-like object&lt;/strong&gt;. A stream can be any file on your disk, a network socket, or perhaps an in-memory buffer.&lt;/p&gt;
&lt;p&gt;In addition to this, there are three standard streams provided by the operating system:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;stdin&lt;/code&gt;:&lt;/strong&gt; standard input&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;stdout&lt;/code&gt;:&lt;/strong&gt; standard output&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;stderr&lt;/code&gt;:&lt;/strong&gt; standard error&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardd994b2&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;#collapsed994b2&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsed994b2&quot;&gt;Standard Streams&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsed994b2&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsed994b2&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsed994b2&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardd994b2&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;strong&gt;Standard output&lt;/strong&gt; is what you see in the terminal when you run various command-line programs including your own &lt;a href=&quot;https://realpython.com/run-python-scripts/&quot;&gt;Python scripts&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; cat hello.py 
&lt;span class=&quot;go&quot;&gt;print(&amp;#39;This will appear on stdout&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python hello.py
&lt;span class=&quot;go&quot;&gt;This will appear on stdout&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unless otherwise instructed, &lt;code&gt;print()&lt;/code&gt; will default to writing to standard output. However, you can tell your operating system to temporarily swap out &lt;code&gt;stdout&lt;/code&gt; for a file stream, so that any output ends up in that file rather than the screen:&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 hello.py &amp;gt; file.txt
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cat file.txt
&lt;span class=&quot;go&quot;&gt;This will appear on stdout&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s called stream redirection.&lt;/p&gt;
&lt;p&gt;The standard error is similar to &lt;code&gt;stdout&lt;/code&gt; in that it also shows up on the screen. Nonetheless, it&amp;rsquo;s a separate stream, whose purpose is to log error messages for diagnostics. By redirecting one or both of them, you can keep things clean.&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; To redirect &lt;code&gt;stderr&lt;/code&gt;, you need to know about &lt;strong&gt;file descriptors&lt;/strong&gt;, also known as &lt;strong&gt;file handles&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;They&amp;rsquo;re arbitrary, albeit constant, numbers associated with standard streams. Below, you&amp;rsquo;ll find a summary of the file descriptors for a family of POSIX-compliant operating systems:&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;Stream&lt;/th&gt;
&lt;th&gt;File Descriptor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stdin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stdout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stderr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Knowing those descriptors allows you to redirect one or more streams at a time:&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;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./program &amp;gt; out.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Redirect &lt;code&gt;stdout&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./program 2&amp;gt; err.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Redirect &lt;code&gt;stderr&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./program &amp;gt; out.txt 2&amp;gt; err.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Redirect &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; to separate files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./program &amp;amp;&amp;gt; out_err.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Redirect &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; to the same file&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;&amp;gt;&lt;/code&gt; is the same as &lt;code&gt;1&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Some programs use different coloring to distinguish between messages printed to &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/pycharm-console-streams.69affb3462e4.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/pycharm-console-streams.69affb3462e4.png&quot; width=&quot;999&quot; height=&quot;286&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-console-streams.69affb3462e4.png&amp;amp;w=249&amp;amp;sig=6f17bc7db6fe5ea5fb93f3575f95a4d46eb88af0 249w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycharm-console-streams.69affb3462e4.png&amp;amp;w=499&amp;amp;sig=ccfce4ba25553f534f07f65b483f9af2b106109b 499w, https://files.realpython.com/media/pycharm-console-streams.69affb3462e4.png 999w&quot; sizes=&quot;75vw&quot; alt=&quot;The output of a program executed in PyCharm&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Run Tool Window in PyCharm&lt;/figcaption&gt;&lt;/figure&gt;


&lt;p&gt;While both &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; are write-only, &lt;code&gt;stdin&lt;/code&gt; is read-only. You can think of standard input as your keyboard, but just like with the other two, you can swap out &lt;code&gt;stdin&lt;/code&gt; for a file to read data from.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;In Python, you can access all standard streams through the built-in &lt;code&gt;sys&lt;/code&gt; module:&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;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;_io.TextIOWrapper name=&amp;#39;&amp;lt;stdin&amp;gt;&amp;#39; mode=&amp;#39;r&amp;#39; encoding=&amp;#39;UTF-8&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;_io.TextIOWrapper name=&amp;#39;&amp;lt;stdout&amp;gt;&amp;#39; mode=&amp;#39;w&amp;#39; encoding=&amp;#39;UTF-8&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;_io.TextIOWrapper name=&amp;#39;&amp;lt;stderr&amp;gt;&amp;#39; mode=&amp;#39;w&amp;#39; encoding=&amp;#39;UTF-8&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, these predefined values resemble file-like objects with &lt;code&gt;mode&lt;/code&gt; and &lt;code&gt;encoding&lt;/code&gt; attributes as well as &lt;code&gt;.read()&lt;/code&gt; and &lt;code&gt;.write()&lt;/code&gt; methods among many others.&lt;/p&gt;
&lt;p&gt;By default, &lt;code&gt;print()&lt;/code&gt; is bound to &lt;code&gt;sys.stdout&lt;/code&gt; through its &lt;code&gt;file&lt;/code&gt; argument, but you can change that. Use that keyword argument to indicate a file that was open in write or append mode, so that messages go straight to it:&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;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.txt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;s1&quot;&gt;&amp;#39;w&amp;#39;&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;file_object&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 world&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will make your code immune to stream redirection at the operating system level, which might or might not be desired.&lt;/p&gt;
&lt;p&gt;For more information on &lt;a href=&quot;https://realpython.com/working-with-files-in-python/&quot;&gt;working with files in Python&lt;/a&gt;, you can check out &lt;a href=&quot;https://realpython.com/read-write-files-python&quot;&gt;Reading and Writing Files in Python (Guide)&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; Don&amp;rsquo;t try using &lt;code&gt;print()&lt;/code&gt; for writing binary data as it&amp;rsquo;s only well suited for text.&lt;/p&gt;
&lt;p&gt;Just call the binary file&amp;rsquo;s &lt;code&gt;.write()&lt;/code&gt; 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;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.dat&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file_object&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;nb&quot;&gt;bytes&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;n&quot;&gt;file_object&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;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xff&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;If you wanted to write raw bytes on the standard output, then this will fail too because &lt;code&gt;sys.stdout&lt;/code&gt; is a character stream:&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;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&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;nb&quot;&gt;bytes&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;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;write() argument must be str, not bytes&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You must dig deeper to get a handle of the underlying byte stream instead:&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;n&quot;&gt;num_bytes_written&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&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;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x41\x0a&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;A&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This prints an uppercase letter &lt;code&gt;A&lt;/code&gt; and a newline character, which correspond to decimal values of 65 and 10 in ASCII. However, they&amp;rsquo;re encoded using hexadecimal notation in the bytes literal.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;print()&lt;/code&gt; has no control over &lt;a href=&quot;https://realpython.com/python-encodings-guide/&quot;&gt;character encoding&lt;/a&gt;. It&amp;rsquo;s the stream&amp;rsquo;s responsibility to encode received Unicode strings into bytes correctly. In most cases, you won&amp;rsquo;t set the encoding yourself, because the default UTF-8 is what you want. If you really need to, perhaps for legacy systems, you can use the &lt;code&gt;encoding&lt;/code&gt; argument of &lt;code&gt;open()&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;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.txt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;s1&quot;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;iso-8859-1&amp;#39;&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;file_object&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;über naïve café&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of a real file existing somewhere in your file system, you can provide a fake one, which would reside in your computer&amp;rsquo;s memory. You&amp;rsquo;ll use this technique later for mocking &lt;code&gt;print()&lt;/code&gt; in unit tests:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fake_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StringIO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;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 world&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fake_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fake_file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;hello world\n&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you got to this point, then you&amp;rsquo;re left with only one keyword argument in &lt;code&gt;print()&lt;/code&gt;, which you&amp;rsquo;ll see in the next subsection. It&amp;rsquo;s probably the least used of them all. Nevertheless, there are times when it&amp;rsquo;s absolutely necessary.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card80f59e&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;#collapse80f59e&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse80f59e&quot;&gt;Syntax in Python 2&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse80f59e&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse80f59e&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse80f59e&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card80f59e&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;There&amp;rsquo;s a special syntax in Python 2 for replacing the default &lt;code&gt;sys.stdout&lt;/code&gt; with a custom file in the &lt;code&gt;print&lt;/code&gt; statement:&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;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.txt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;s1&quot;&gt;&amp;#39;w&amp;#39;&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;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hello world&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because strings and bytes are represented with the same &lt;code&gt;str&lt;/code&gt; type in Python 2, the &lt;code&gt;print&lt;/code&gt; statement can handle binary data just fine:&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;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.dat&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;s1&quot;&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x41\x0a&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Although, there&amp;rsquo;s a problem with character encoding. The &lt;code&gt;open()&lt;/code&gt; function in Python 2 lacks the &lt;code&gt;encoding&lt;/code&gt; parameter, which would often result in the dreadful  &lt;code&gt;UnicodeEncodeError&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.txt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;s1&quot;&gt;&amp;#39;w&amp;#39;&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;file_object&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;unicode_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xfc&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ber na&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ve caf&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xe9&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unicode_text&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;UnicodeEncodeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;ascii&amp;#39; codec can&amp;#39;t encode character u&amp;#39;\xfc&amp;#39;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how non-Latin characters must be escaped in both Unicode and string literals to avoid a syntax error. Take a look at 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;n&quot;&gt;unicode_literal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xfc&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ber na&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ve caf&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xe9&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string_literal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc3\xbc&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ber na&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc3\xaf&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ve caf&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc3\xa9&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, you could specify source code encoding according to &lt;a href=&quot;https://www.python.org/dev/peps/pep-0263/&quot;&gt;PEP 263&lt;/a&gt; at the top of the file, but that wasn&amp;rsquo;t the best practice due to portability issues:&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 python2&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: utf-8 -*-&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;unescaped_unicode_literal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;über naïve café&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;unescaped_string_literal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;über naïve café&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your best bet is to encode the Unicode string just before printing it. You can do this manually:&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;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.txt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;s1&quot;&gt;&amp;#39;w&amp;#39;&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;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;unicode_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xfc&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ber na&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ve caf&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xe9&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;encoded_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unicode_text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoded_text&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, a more convenient option is to use the built-in &lt;code&gt;codecs&lt;/code&gt; module:&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;codecs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;codecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;file.txt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;utf-8&amp;#39;&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;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;unicode_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xfc&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ber na&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ve caf&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xe9&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unicode_text&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;ll take care of making appropriate conversions when you need to read or write files.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h3 id=&quot;buffering-print-calls&quot;&gt;Buffering Print Calls&lt;/h3&gt;
&lt;p&gt;In the previous subsection, you learned that &lt;code&gt;print()&lt;/code&gt; delegates printing to a file-like object such as &lt;code&gt;sys.stdout&lt;/code&gt;. Some streams, however, buffer certain I/O operations to enhance performance, which can get in the way. Let&amp;rsquo;s take a look at an example.&lt;/p&gt;
&lt;p&gt;Imagine you were writing a countdown timer, which should append the remaining time to the same line every second:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;3...2...1...Go!
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your first attempt may look 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;num_seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countdown&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countdown&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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;countdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;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;k&quot;&gt;else&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;Go!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As long as the &lt;code&gt;countdown&lt;/code&gt; variable is greater than zero, the code keeps appending text without a trailing newline and then goes to sleep for one second.  Finally, when the countdown is finished, it prints &lt;code&gt;Go!&lt;/code&gt; and terminates the line.&lt;/p&gt;
&lt;p&gt;Unexpectedly, instead of counting down every second, the program idles wastefully for three seconds, and then suddenly prints the entire line at once:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/print_countdown.ba38eb242915.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/print_countdown.ba38eb242915.gif&quot; width=&quot;576&quot; height=&quot;236&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/print_countdown.ba38eb242915.gif&amp;amp;w=144&amp;amp;sig=1084be0d7eb723df32fe7d0e16f06724e2666c04 144w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/print_countdown.ba38eb242915.gif&amp;amp;w=288&amp;amp;sig=0618ab48bb5a9e8b729d8a97e4736f78f9b3560f 288w, https://files.realpython.com/media/print_countdown.ba38eb242915.gif 576w&quot; sizes=&quot;75vw&quot; alt=&quot;Terminal with buffered output&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s because the operating system buffers subsequent writes to the standard output in this case. You need to know that there are three kinds of streams with respect to buffering:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Unbuffered&lt;/li&gt;
&lt;li&gt;Line-buffered&lt;/li&gt;
&lt;li&gt;Block-buffered&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Unbuffered&lt;/strong&gt; is self-explanatory, that is, no buffering is taking place, and all writes have immediate effect. A &lt;strong&gt;line-buffered&lt;/strong&gt; stream waits before firing any I/O calls until a line break appears somewhere in the buffer, whereas a &lt;strong&gt;block-buffered&lt;/strong&gt; one simply allows the buffer to fill up to a certain size regardless of its content. Standard output is both &lt;strong&gt;line-buffered&lt;/strong&gt; and &lt;strong&gt;block-buffered&lt;/strong&gt;, depending on which event comes first.&lt;/p&gt;
&lt;p&gt;Buffering helps to reduce the number of expensive I/O calls. Think about sending messages over a high-latency network, for example. When you connect to a remote server to execute commands over the SSH protocol, each of your keystrokes may actually produce an individual data packet, which is orders of magnitude bigger than its payload. What an overhead! It would make sense to wait until at least a few characters are typed and then send them together. That&amp;rsquo;s where buffering steps in.&lt;/p&gt;
&lt;p&gt;On the other hand, buffering can sometimes have undesired effects as you just saw with the countdown example. To fix it, you can simply tell &lt;code&gt;print()&lt;/code&gt; to forcefully flush the stream without waiting for a newline character in the buffer using its &lt;code&gt;flush&lt;/code&gt; flag:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;countdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s all. Your countdown should work as expected now, but don&amp;rsquo;t take my word for it. Go ahead and test it to see the difference.&lt;/p&gt;
&lt;p&gt;Congratulations! At this point, you&amp;rsquo;ve seen examples of calling &lt;code&gt;print()&lt;/code&gt; that cover all of its parameters. You know their purpose and when to use them. Understanding the signature is only the beginning, however. In the upcoming sections, you&amp;rsquo;ll see why.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardec4147&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;#collapseec4147&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapseec4147&quot;&gt;Syntax in Python 2&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapseec4147&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapseec4147&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapseec4147&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardec4147&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;There isn&amp;rsquo;t an easy way to flush the stream in Python 2, because the &lt;code&gt;print&lt;/code&gt; statement doesn&amp;rsquo;t allow for it by itself. You need to get a handle of its lower-level layer, which is the standard output, and call it 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;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;sys&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;num_seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countdown&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countdown&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;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;...&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countdown&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;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;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;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Go!&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, you could disable buffering of the standard streams either by providing the &lt;code&gt;-u&lt;/code&gt; flag to the Python interpreter or by setting up the &lt;code&gt;PYTHONUNBUFFERED&lt;/code&gt; environment variable:&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; python2 -u countdown.py
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;PYTHONUNBUFFERED&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; python2 countdown.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that &lt;code&gt;print()&lt;/code&gt; was backported to Python 2 and made available through the &lt;code&gt;__future__&lt;/code&gt; module. Unfortunately, it doesn&amp;rsquo;t come with the &lt;code&gt;flush&lt;/code&gt; parameter:&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;__future__&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;print_function&lt;/span&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;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Help on built-in function print in module __builtin__:&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;print(...)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    print(value, ..., sep=&amp;#39; &amp;#39;, end=&amp;#39;\n&amp;#39;, file=sys.stdout)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What you&amp;rsquo;re seeing here is a &lt;strong&gt;docstring&lt;/strong&gt; of the &lt;code&gt;print()&lt;/code&gt; function. You can display docstrings of various objects in Python using the built-in &lt;code&gt;help()&lt;/code&gt; function.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h3 id=&quot;printing-custom-data-types&quot;&gt;Printing Custom Data Types&lt;/h3&gt;
&lt;p&gt;Up until now, you only dealt with built-in data types such as strings and numbers, but you&amp;rsquo;ll often want to print your own abstract data types. Let&amp;rsquo;s have a look at different ways of defining them.&lt;/p&gt;
&lt;p&gt;For simple objects without any logic, whose purpose is to carry data, you&amp;rsquo;ll typically take advantage of &lt;a href=&quot;https://docs.python.org/3/library/collections.html#collections.namedtuple&quot;&gt;&lt;code&gt;namedtuple&lt;/code&gt;&lt;/a&gt;, which is available in the standard library. Named tuples have a neat textual representation out of the box:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Person&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;name age&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;jdoe&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;s1&quot;&gt;&amp;#39;John Doe&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;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;jdoe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Person(name=&amp;#39;John Doe&amp;#39;, age=42)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s great as long as holding data is enough, but in order to add behaviors to the &lt;code&gt;Person&lt;/code&gt; type, you&amp;rsquo;ll eventually need to define a class. Take a look at 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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&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;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&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;name&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;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you now create an instance of the &lt;code&gt;Person&lt;/code&gt; class and try to print it, you&amp;rsquo;ll get this bizarre output, which is quite different from the equivalent &lt;code&gt;namedtuple&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;jdoe&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;s1&quot;&gt;&amp;#39;John Doe&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;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;jdoe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;__main__.Person object at 0x7fcac3fed1d0&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s the default representation of objects, which comprises their address in memory, the corresponding class name and a module in which they were defined. You&amp;rsquo;ll fix that in a bit, but just for the record, as a quick workaround you could combine &lt;code&gt;namedtuple&lt;/code&gt; and a custom class through &lt;a href=&quot;https://realpython.com/inheritance-composition-python/&quot;&gt;inheritance&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;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Person&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;name age&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your &lt;code&gt;Person&lt;/code&gt; class has just become a specialized kind of &lt;code&gt;namedtuple&lt;/code&gt; with two attributes, which you can customize.&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, the &lt;code&gt;pass&lt;/code&gt; statement can be replaced with the &lt;a href=&quot;https://docs.python.org/dev/library/constants.html#Ellipsis&quot;&gt;ellipsis&lt;/a&gt; (&lt;code&gt;...&lt;/code&gt;) literal to indicate a placeholder:&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;delta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This prevents the interpreter from raising &lt;code&gt;IndentationError&lt;/code&gt; due to missing indented block of code.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;rsquo;s better than a plain &lt;code&gt;namedtuple&lt;/code&gt;, because not only do you get printing right for free, but you can also add custom methods and properties to the class. However, it solves one problem while introducing another. Remember that tuples, including named tuples, are immutable in Python, so they can&amp;rsquo;t change their values once created.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s true that designing immutable data types is desirable, but in many cases, you&amp;rsquo;ll want them to allow for change, so you&amp;rsquo;re back with regular classes again.&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; Following other languages and frameworks, Python 3.7 introduced &lt;a href=&quot;https://realpython.com/python-data-classes/&quot;&gt;data classes&lt;/a&gt;, which you can think of as mutable tuples. This way, you get the best of both worlds:&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;dataclasses&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataclass&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@dataclass&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&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;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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;age&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;gp&quot;&gt;... &lt;/span&gt;    
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;celebrate_birthday&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;gp&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;age&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;jdoe&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;s1&quot;&gt;&amp;#39;John Doe&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jdoe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;celebrate_birthday&lt;/span&gt;&lt;span class=&quot;p&quot;&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;jdoe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Person(name=&amp;#39;John Doe&amp;#39;, age=43)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The syntax for &lt;a href=&quot;https://www.python.org/dev/peps/pep-0526/&quot;&gt;variable annotations&lt;/a&gt;, which is required to specify class fields with their corresponding types, was defined in Python 3.6.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;From earlier subsections, you already know that &lt;code&gt;print()&lt;/code&gt; implicitly calls the built-in &lt;code&gt;str()&lt;/code&gt; function to convert its positional arguments into strings. Indeed, calling &lt;code&gt;str()&lt;/code&gt; manually against an instance of the regular &lt;code&gt;Person&lt;/code&gt; class yields the same result as printing it:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jdoe&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;s1&quot;&gt;&amp;#39;John Doe&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jdoe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;&amp;lt;__main__.Person object at 0x7fcac3fed1d0&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;str()&lt;/code&gt;, in turn, looks for one of two &lt;strong&gt;magic methods&lt;/strong&gt; within the class body, which you typically implement. If it doesn&amp;rsquo;t find one, then it falls back to the ugly default representation. Those magic methods are, in order of search:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;def __str__(self)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;def __repr__(self)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first one is recommended to return a short, human-readable text, which includes information from the most relevant attributes. After all, you don&amp;rsquo;t want to expose sensitive data, such as user passwords, when printing objects.&lt;/p&gt;
&lt;p&gt;However, the other one should provide complete information about an object, to allow for restoring its state from a string. Ideally, it should return valid Python code, so that you can pass it directly to &lt;code&gt;eval()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jdoe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;Person(name=&amp;#39;John Doe&amp;#39;, age=42)&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&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;nb&quot;&gt;repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jdoe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;class &amp;#39;__main__.Person&amp;#39;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice the use of another built-in function, &lt;code&gt;repr()&lt;/code&gt;, which always tries to call &lt;code&gt;.__repr__()&lt;/code&gt; in an object, but falls back to the default representation if it doesn&amp;rsquo;t find that method.&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; Even though &lt;code&gt;print()&lt;/code&gt; itself uses &lt;code&gt;str()&lt;/code&gt; for type casting, some compound data types delegate that call to &lt;code&gt;repr()&lt;/code&gt; on their members. This happens to lists and tuples, for example.&lt;/p&gt;
&lt;p&gt;Consider this class with both magic methods, which return alternative string representations of the same 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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&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;login&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;bp&quot;&gt;self&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;login&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;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__repr__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;User(&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{self.login}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{self.password}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;#39;)&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you print a single object of the &lt;code&gt;User&lt;/code&gt; class, then you won&amp;rsquo;t see the password, because &lt;code&gt;print(user)&lt;/code&gt; will call &lt;code&gt;str(user)&lt;/code&gt;, which eventually will invoke &lt;code&gt;user.__str__()&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;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;jdoe&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;s3cret&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;jdoe&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, if you put the same &lt;code&gt;user&lt;/code&gt; variable inside a list by wrapping it in square brackets, then the password will become clearly visible:&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;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[User(&amp;#39;jdoe&amp;#39;, &amp;#39;s3cret&amp;#39;)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s because sequences, such as lists and tuples, implement their &lt;code&gt;.__str__()&lt;/code&gt; method so that all of their elements are first converted with &lt;code&gt;repr()&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Python gives you a lot of freedom when it comes to defining your own data types if none of the built-in ones meet your needs. Some of them, such as named tuples and data classes, offer string representations that look good without requiring any work on your part. Still, for the most flexibility, you&amp;rsquo;ll have to define a class and override its magic methods described above.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card996300&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;#collapse996300&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse996300&quot;&gt;Syntax in Python 2&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse996300&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse996300&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse996300&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card996300&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;The semantics of &lt;code&gt;.__str__()&lt;/code&gt; and &lt;code&gt;.__repr__()&lt;/code&gt; didn&amp;rsquo;t change since Python 2, but you must remember that strings were nothing more than glorified byte arrays back then. To convert your objects into proper Unicode, which was a separate data type, you&amp;rsquo;d have to provide yet another magic method: &lt;code&gt;.__unicode__()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of the same &lt;code&gt;User&lt;/code&gt; class in Python 2:&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;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fm&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;login&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;bp&quot;&gt;self&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;login&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;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fm&quot;&gt;__unicode__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;login&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fm&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;unicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;utf-8&amp;#39;&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;fm&quot;&gt;__repr__&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;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;User(&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;#39;)&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;bp&quot;&gt;self&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;unicode_escape&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, this implementation delegates some work to avoid duplication by calling the built-in &lt;code&gt;unicode()&lt;/code&gt; function on itself.&lt;/p&gt;
&lt;p&gt;Both &lt;code&gt;.__str__()&lt;/code&gt; and &lt;code&gt;.__repr__()&lt;/code&gt; methods must return strings, so they encode Unicode characters into specific byte representations called &lt;strong&gt;character sets&lt;/strong&gt;. UTF-8 is the most widespread and safest encoding, while &lt;code&gt;unicode_escape&lt;/code&gt; is a special constant to express funky characters, such as &lt;code&gt;é&lt;/code&gt;, as escape sequences in plain ASCII, such as &lt;code&gt;\xe9&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;print&lt;/code&gt; statement is looking for the magic &lt;code&gt;.__str__()&lt;/code&gt; method in the class, so the chosen &lt;strong&gt;charset&lt;/strong&gt; must correspond to the one used by the terminal. For example, default encoding in DOS and Windows is CP 852 rather than UTF-8, so running this can result in a &lt;code&gt;UnicodeEncodeError&lt;/code&gt; or even garbled output:&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;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\u043d\u0438\u043a\u0438\u0442\u0430&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;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;s3cret&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;đŻđŞđ║đŞĐéđ░&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, if you ran the same code on a system with UTF-8 encoding, then you&amp;rsquo;d get the proper spelling of a popular Russian 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;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\u043d\u0438\u043a\u0438\u0442\u0430&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;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;s3cret&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;никита&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s recommended to convert strings to Unicode as early as possible, for example, when you&amp;rsquo;re reading data from a file, and use it consistently everywhere in your code. At the same time, you should encode Unicode back to the chosen character set right before presenting it to the user.&lt;/p&gt;
&lt;p&gt;It seems as if you have more control over string representation of objects in Python 2 because there&amp;rsquo;s no magic &lt;code&gt;.__unicode__()&lt;/code&gt; method in Python 3 anymore. You may be asking yourself if it&amp;rsquo;s possible to convert an object to its byte string representation rather than a Unicode string in Python 3. It&amp;rsquo;s possible, with a special &lt;code&gt;.__bytes__()&lt;/code&gt; method that does just that:&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&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;login&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;gp&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;login&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;gp&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;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__bytes__&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;c1&quot;&gt;# Python 3&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;bp&quot;&gt;self&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\u043d\u0438\u043a\u0438\u0442\u0430&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;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;s3cret&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;\xd0\xbd\xd0\xb8\xd0\xba\xd0\xb8\xd1\x82\xd0\xb0&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using the built-in &lt;code&gt;bytes()&lt;/code&gt; function on an instance delegates the call to its &lt;code&gt;__bytes__()&lt;/code&gt; method defined in the corresponding class.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h2 id=&quot;understanding-python-print&quot;&gt;Understanding Python Print&lt;/h2&gt;
&lt;p&gt;You know &lt;strong&gt;how&lt;/strong&gt; to use &lt;code&gt;print()&lt;/code&gt; quite well at this point, but knowing &lt;strong&gt;what&lt;/strong&gt; it is will allow you to use it even more effectively and consciously. After reading this section, you&amp;rsquo;ll understand how printing in Python has improved over the years.&lt;/p&gt;
&lt;h3 id=&quot;print-is-a-function-in-python-3&quot;&gt;Print Is a Function in Python 3&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;ve seen that &lt;code&gt;print()&lt;/code&gt; is a function in Python 3. More specifically, it&amp;rsquo;s a built-in function, which means that you don&amp;rsquo;t need to import it from anywhere:&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;go&quot;&gt;&amp;lt;built-in function print&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s always available in the global namespace so that you can call it directly, but you can also access it through a module from the standard library:&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;builtins&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;built-in function print&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This way, you can avoid name collisions with custom functions. Let&amp;rsquo;s say you wanted to &lt;strong&gt;redefine&lt;/strong&gt; &lt;code&gt;print()&lt;/code&gt; so that it doesn&amp;rsquo;t append a trailing newline. At the same time, you wanted to rename the original function to something like &lt;code&gt;println()&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;builtins&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&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;print&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&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;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;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;println&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;go&quot;&gt;hello&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;s1&quot;&gt;&amp;#39;hello&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;hello&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you have two separate printing functions just like in the Java programming language. You&amp;rsquo;ll define custom &lt;code&gt;print()&lt;/code&gt; functions in the &lt;a href=&quot;#mocking-python-print-in-unit-tests&quot;&gt;mocking section&lt;/a&gt; later as well. Also, note that you wouldn&amp;rsquo;t be able to overwrite &lt;code&gt;print()&lt;/code&gt; in the first place if it wasn&amp;rsquo;t a function.&lt;/p&gt;
&lt;p&gt;On the other hand, &lt;code&gt;print()&lt;/code&gt; isn&amp;rsquo;t a function in the mathematical sense, because it doesn&amp;rsquo;t return any meaningful value other than the implicit &lt;code&gt;None&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;value&lt;/span&gt; &lt;span class=&quot;o&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 world&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;hello world&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;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;None&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Such functions are, in fact, procedures or subroutines that you call to achieve some kind of side-effect, which ultimately is a change of a global state. In the case of &lt;code&gt;print()&lt;/code&gt;, that side-effect is showing a message on the standard output or writing to a file.&lt;/p&gt;
&lt;p&gt;Because &lt;code&gt;print()&lt;/code&gt; is a function, it has a well-defined signature with known attributes. You can quickly find its &lt;strong&gt;documentation&lt;/strong&gt; using the editor of your choice, without having to remember some weird syntax for performing a certain task.&lt;/p&gt;
&lt;p&gt;Besides, functions are easier to &lt;strong&gt;extend&lt;/strong&gt;. Adding a new feature to a function is as easy as adding another keyword argument, whereas changing the language to support that new feature is much more cumbersome. Think of stream redirection or buffer flushing, for example.&lt;/p&gt;
&lt;p&gt;Another benefit of &lt;code&gt;print()&lt;/code&gt; being a function is &lt;strong&gt;composability&lt;/strong&gt;. Functions are so-called &lt;a href=&quot;https://realpython.com/lessons/functions-first-class-objects-python/&quot;&gt;first-class objects&lt;/a&gt; or &lt;a href=&quot;https://realpython.com/lessons/functions-are-first-class-citizens-python/&quot;&gt;first-class citizens&lt;/a&gt; in Python, which is a fancy way of saying they&amp;rsquo;re values just like strings or numbers. This way, you can assign a function to a variable, pass it to another function, or even return one from another. &lt;code&gt;print()&lt;/code&gt; isn&amp;rsquo;t different in this regard. For instance, you can take advantage of it for dependency injection:&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;download&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;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&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;log&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;Downloading &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;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;custom_print&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;k&quot;&gt;pass&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Do not print anything&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/js/app.js&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, the &lt;code&gt;log&lt;/code&gt; parameter lets you inject a callback function, which defaults to &lt;code&gt;print()&lt;/code&gt; but can be any callable. In this example, printing is completely disabled by substituting &lt;code&gt;print()&lt;/code&gt; with a dummy function that does nothing.&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;dependency&lt;/strong&gt; is any piece of code required by another bit of code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dependency injection&lt;/strong&gt; is a technique used in code design to make it more testable, reusable, and open for extension. You can achieve it by referring to dependencies indirectly through abstract interfaces and by providing them in a &lt;strong&gt;push&lt;/strong&gt; rather than &lt;strong&gt;pull&lt;/strong&gt; fashion.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a funny explanation of dependency injection circulating on the Internet:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dependency injection for five-year-olds&lt;/p&gt;
&lt;p&gt;When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesn&amp;rsquo;t want you to have. You might even be looking for something we don&amp;rsquo;t even have or which has expired.&lt;/p&gt;
&lt;p&gt;What you should be doing is stating a need, &amp;ldquo;I need something to drink with lunch,&amp;rdquo; and then we will make sure you have something when you sit down to eat.&lt;/p&gt;
&lt;p&gt;&amp;mdash; &lt;em&gt;John Munsch, 28 October 2009.&lt;/em&gt; (&lt;a href=&quot;https://stackoverflow.com/a/1638961&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;p&gt;Composition allows you to combine a few functions into a new one of the same kind. Let&amp;rsquo;s see this in action by specifying a custom &lt;code&gt;error()&lt;/code&gt; function that prints to the standard error stream and prefixes all messages with a given log level:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;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;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;n&quot;&gt;redirect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partial&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;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix&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;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;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;prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;redirect&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;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;[ERROR]&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Something went wrong&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[ERROR] Something went wrong&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This custom function uses &lt;strong&gt;partial functions&lt;/strong&gt; to achieve the desired effect. It&amp;rsquo;s an advanced concept borrowed from the &lt;a href=&quot;https://realpython.com/courses/functional-programming-python/&quot;&gt;functional programming&lt;/a&gt; paradigm, so you don&amp;rsquo;t need to go too deep into that topic for now. However, if you&amp;rsquo;re interested in this topic, I recommend taking a look at the &lt;a href=&quot;https://pymotw.com/3/functools/&quot;&gt;&lt;code&gt;functools&lt;/code&gt;&lt;/a&gt; module.&lt;/p&gt;
&lt;p&gt;Unlike statements, functions are values. That means you can mix them with &lt;strong&gt;expressions&lt;/strong&gt;, in particular, &lt;a href=&quot;https://realpython.com/python-lambda/&quot;&gt;&lt;strong&gt;lambda&lt;/strong&gt; expressions&lt;/a&gt;. Instead of defining a full-blown function to replace &lt;code&gt;print()&lt;/code&gt; with, you can make an anonymous lambda expression that calls it:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/js/app.js&amp;#39;&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;msg&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;[INFO]&amp;#39;&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;go&quot;&gt;[INFO] Downloading /js/app.js&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, because a lambda expression is defined in place, there&amp;rsquo;s no way of referring to it elsewhere in the code.&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, you can&amp;rsquo;t put statements, such as assignments, conditional statements, loops, and so on, in an &lt;strong&gt;anonymous lambda function&lt;/strong&gt;. It has to be a single expression!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Another kind of expression is a ternary conditional expression:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;jdoe&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hi!&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;n&quot;&gt;user&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;k&quot;&gt;else&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;Hi, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{user}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Hi, jdoe.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python has both &lt;a href=&quot;https://realpython.com/python-conditional-statements/&quot;&gt;conditional statements&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-conditional-statements/#conditional-expressions-pythons-ternary-operator&quot;&gt;conditional expressions&lt;/a&gt;. The latter is evaluated to a single value that can be assigned to a variable or passed to a function. In the example above, you&amp;rsquo;re interested in the side-effect rather than the value, which evaluates to &lt;code&gt;None&lt;/code&gt;, so you simply ignore it.&lt;/p&gt;
&lt;p&gt;As you can see, functions allow for an elegant and extensible solution, which is consistent with the rest of the language. In the next subsection, you&amp;rsquo;ll discover how not having &lt;code&gt;print()&lt;/code&gt; as a function caused a lot of headaches.&lt;/p&gt;
&lt;h3 id=&quot;print-was-a-statement-in-python-2&quot;&gt;Print Was a Statement in Python 2&lt;/h3&gt;
&lt;p&gt;A &lt;strong&gt;statement&lt;/strong&gt; is an instruction that may evoke a side-effect when executed but never evaluates to a value. In other words, you wouldn&amp;rsquo;t be able to print a statement or assign it to a variable 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;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hello world&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s a syntax error in Python 2.&lt;/p&gt;
&lt;p&gt;Here are a few more examples of statements in Python:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;assignment:&lt;/strong&gt; &lt;code&gt;=&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;conditional:&lt;/strong&gt; &lt;code&gt;if&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;loop:&lt;/strong&gt; &lt;code&gt;while&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;assertion&lt;/strong&gt;: &lt;code&gt;assert&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Python 3.8 brings a controversial &lt;strong&gt;walrus operator&lt;/strong&gt; (&lt;code&gt;:=&lt;/code&gt;), which is an &lt;a href=&quot;https://www.python.org/dev/peps/pep-0572/&quot;&gt;assignment expression&lt;/a&gt;. With it, you can evaluate an expression and assign the result to a variable at the same time, even within another expression!&lt;/p&gt;
&lt;p&gt;Take a look at this example, which calls an expensive function once and then reuses the result for further computation:&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;# Python 3.8+&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is useful for simplifying the code without losing its efficiency. Typically, performant code tends to be more verbose:&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;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;The controversy behind this new piece of syntax caused a lot of argument. An abundance of negative comments and heated debates eventually led Guido van Rossum to step down from the &lt;strong&gt;Benevolent Dictator For Life&lt;/strong&gt; or BDFL position.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Statements are usually comprised of reserved keywords such as &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, or &lt;code&gt;print&lt;/code&gt; that have fixed meaning in the language. You can&amp;rsquo;t use them to name your variables or other symbols. That&amp;rsquo;s why redefining or mocking the &lt;code&gt;print&lt;/code&gt; statement isn&amp;rsquo;t possible in Python 2. You&amp;rsquo;re stuck with what you get.&lt;/p&gt;
&lt;p&gt;Furthermore, you can&amp;rsquo;t print from anonymous functions, because statements aren&amp;rsquo;t accepted in lambda expressions:&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;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hello world&amp;#39;&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;
    &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hello world&amp;#39;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;SyntaxError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;invalid syntax&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The syntax of the &lt;code&gt;print&lt;/code&gt; statement is ambiguous. Sometimes you can add parentheses around the message, and they&amp;rsquo;re completely optional:&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;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait...&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Please wait...&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Please wait...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Please wait...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At other times they change how the message is printed:&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;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;My name is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My name is John&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;My name is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;My name is&amp;#39;, &amp;#39;John&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;String concatenation can raise a &lt;code&gt;TypeError&lt;/code&gt; due to incompatible types, which you have to handle manually, for example:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;jdoe&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;years old&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;jdoe is 42 years old&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Compare this with similar code in Python 3, which leverages sequence unpacking:&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;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;jdoe&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;is&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;years old&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&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;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Python 3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;jdoe is 42 years old&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There aren&amp;rsquo;t any keyword arguments for common tasks such as flushing the buffer or stream redirection. You need to remember the quirky syntax instead. Even the built-in &lt;code&gt;help()&lt;/code&gt; function isn&amp;rsquo;t that helpful with regards to the &lt;code&gt;print&lt;/code&gt; statement:&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;help&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&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;k&quot;&gt;print&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;gr&quot;&gt;SyntaxError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;invalid syntax&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Trailing newline removal doesn&amp;rsquo;t work quite right, because it adds an unwanted space. You can&amp;rsquo;t compose multiple &lt;code&gt;print&lt;/code&gt; statements together, and, on top of that, you have to be extra diligent about character encoding.&lt;/p&gt;
&lt;p&gt;The list of problems goes on and on. If you&amp;rsquo;re curious, you can jump back to the &lt;a href=&quot;#printing-in-a-nutshell&quot;&gt;previous section&lt;/a&gt; and look for more detailed explanations of the syntax in Python 2.&lt;/p&gt;
&lt;p&gt;However, you can mitigate some of those problems with a much simpler approach. It turns out the &lt;code&gt;print()&lt;/code&gt; function was backported to ease the migration to Python 3. You can import it from a special &lt;code&gt;__future__&lt;/code&gt; module, which exposes a selection of language features released in later Python versions.&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 may import future functions as well as baked-in language constructs such as the &lt;code&gt;with&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;To find out exactly what features are available to you, inspect the module:&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;__future__&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__future__&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all_feature_names&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;nested_scopes&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;generators&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;division&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;absolute_import&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;with_statement&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;print_function&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;unicode_literals&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You could also call &lt;code&gt;dir(__future__)&lt;/code&gt;, but that would show a lot of uninteresting internal details of the module.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To enable the &lt;code&gt;print()&lt;/code&gt; function in Python 2, you need to add this import statement at the beginning of your source code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;__future__&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;print_function&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From now on the &lt;code&gt;print&lt;/code&gt; statement is no longer available, but you have the &lt;code&gt;print()&lt;/code&gt; function at your disposal. Note that it isn&amp;rsquo;t the same function like the one in Python 3, because it&amp;rsquo;s missing the &lt;code&gt;flush&lt;/code&gt; keyword argument, but the rest of the arguments are the same.&lt;/p&gt;
&lt;p&gt;Other than that, it doesn&amp;rsquo;t spare you from managing character encodings properly.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of calling the &lt;code&gt;print()&lt;/code&gt; function in Python 2:&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;__future__&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;print_function&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;k&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 am a function in Python&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;major&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;I am a function in Python 2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You now have an idea of how printing in Python evolved and, most importantly, understand why these backward-incompatible changes were necessary. Knowing this will surely help you become a better Python programmer.&lt;/p&gt;
&lt;h2 id=&quot;printing-with-style&quot;&gt;Printing With Style&lt;/h2&gt;
&lt;p&gt;If you thought that printing was only about lighting pixels up on the screen, then technically you&amp;rsquo;d be right. However, there are ways to make it look cool. In this section, you&amp;rsquo;ll find out how to format complex data structures, add colors and other decorations, build interfaces, use animation, and even play sounds with text! &lt;/p&gt;
&lt;h3 id=&quot;pretty-printing-nested-data-structures&quot;&gt;Pretty-Printing Nested Data Structures&lt;/h3&gt;
&lt;p&gt;Computer languages allow you to represent data as well as executable code in a structured way. Unlike Python, however, most languages give you a lot of freedom in using whitespace and formatting. This can be useful, for example in compression, but it sometimes leads to less readable code.&lt;/p&gt;
&lt;p&gt;Pretty-printing is about making a piece of data or code look more appealing to the human eye so that it can be understood more easily. This is done by indenting certain lines, inserting newlines, reordering elements, and so forth.&lt;/p&gt;
&lt;p&gt;Python comes with the &lt;code&gt;pprint&lt;/code&gt; module in its standard library, which will help you in pretty-printing large data structures that don&amp;rsquo;t fit on a single line. Because it prints in a more human-friendly way, many popular &lt;a href=&quot;https://realpython.com/interacting-with-python/&quot;&gt;REPL&lt;/a&gt; tools, including &lt;a href=&quot;https://realpython.com/jupyter-notebook-introduction/&quot;&gt;JupyterLab and IPython&lt;/a&gt;, use it by default in place of the regular &lt;code&gt;print()&lt;/code&gt; function.&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; To toggle pretty printing in IPython, issue the following command:&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;In [1]: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pprint&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Pretty printing has been turned OFF&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;In [2]: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pprint&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Pretty printing has been turned ON&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is an example of &lt;strong&gt;Magic&lt;/strong&gt; in IPython. There are a lot of built-in commands that start with a percent sign (&lt;code&gt;%&lt;/code&gt;), but you can find more on &lt;a href=&quot;https://pypi.org/&quot;&gt;PyPI&lt;/a&gt;, or even create your own.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you don&amp;rsquo;t care about not having access to the original &lt;code&gt;print()&lt;/code&gt; function, then you can replace it with &lt;code&gt;pprint()&lt;/code&gt; in your code using import renaming:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;print&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;go&quot;&gt;&amp;lt;function pprint at 0x7f7a775a3510&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Personally, I like to have both functions at my fingertips, so I&amp;rsquo;d rather use something like &lt;code&gt;pp&lt;/code&gt; as a short alias:&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;pprint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pp&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At first glance, there&amp;rsquo;s hardly any difference between the two functions, and in some cases there&amp;rsquo;s virtually none:&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;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;42&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;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;go&quot;&gt;hello&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pp&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;go&quot;&gt;&amp;#39;hello&amp;#39;  # Did you spot the difference?&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s because &lt;code&gt;pprint()&lt;/code&gt; calls &lt;code&gt;repr()&lt;/code&gt; instead of the usual &lt;code&gt;str()&lt;/code&gt; for type casting, so that you may evaluate its output as Python code if you want to. The differences become apparent as you start feeding it more complex data structures:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;powers&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;n&quot;&gt;x&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;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;pp&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;{&amp;#39;powers&amp;#39;: [0,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            1,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            1024,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            59049,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            1048576,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            9765625,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            60466176,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            282475249,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            1073741824,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            3486784401]}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The function applies reasonable formatting to improve readability, but you can customize it even further with a couple of parameters. For example, you may limit a deeply nested hierarchy by showing an ellipsis below a given level:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;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;USA&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;s1&quot;&gt;&amp;#39;Texas&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;s1&quot;&gt;&amp;#39;Dallas&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;s1&quot;&gt;&amp;#39;Irving&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;pp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;n&quot;&gt;depth&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;go&quot;&gt;{&amp;#39;USA&amp;#39;: {&amp;#39;Texas&amp;#39;: {&amp;#39;Dallas&amp;#39;: [...]}}}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The ordinary &lt;code&gt;print()&lt;/code&gt; also uses ellipses but for displaying recursive data structures, which form a cycle, to avoid stack overflow error:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&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;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&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;go&quot;&gt;[1, 2, 3, [...]]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, &lt;code&gt;pprint()&lt;/code&gt; is more explicit about it by including the unique identity of a self-referencing object:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pp&lt;/span&gt;&lt;span class=&quot;p&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;go&quot;&gt;[1, 2, 3, &amp;lt;Recursion on list with id=140635757287688&amp;gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&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;go&quot;&gt;140635757287688&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last element in the list is the same object as the entire list.&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; Recursive or very large data sets can be dealt with using the &lt;code&gt;reprlib&lt;/code&gt; module 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;reprlib&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reprlib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repr&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;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;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;go&quot;&gt;&amp;#39;[0, 1, 1024, 59049, 1048576, 9765625, ...]&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This module supports most of the built-in types and is used by the Python debugger.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;pprint()&lt;/code&gt; automatically sorts dictionary keys for you before printing, which allows for consistent comparison. When you&amp;rsquo;re comparing strings, you often don&amp;rsquo;t care about a particular order of serialized attributes. Anyways, it&amp;rsquo;s always best to compare actual dictionaries before serialization.&lt;/p&gt;
&lt;p&gt;Dictionaries often represent &lt;a href=&quot;https://realpython.com/python-json/&quot;&gt;JSON data&lt;/a&gt;, which is widely used on the Internet. To correctly serialize a dictionary into a valid JSON-formatted string, you can take advantage of the &lt;code&gt;json&lt;/code&gt; module. It too has pretty-printing capabilities:&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;json&lt;/span&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;s1&quot;&gt;&amp;#39;username&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;jdoe&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;password&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;s3cret&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;ugly&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pretty&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indent&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;n&quot;&gt;sort_keys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ugly&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;quot;username&amp;quot;: &amp;quot;jdoe&amp;quot;, &amp;quot;password&amp;quot;: &amp;quot;s3cret&amp;quot;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pretty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    &amp;quot;password&amp;quot;: &amp;quot;s3cret&amp;quot;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    &amp;quot;username&amp;quot;: &amp;quot;jdoe&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice, however, that you need to handle printing yourself, because it&amp;rsquo;s not something you&amp;rsquo;d typically want to do. Similarly, the &lt;code&gt;pprint&lt;/code&gt; module has an additional &lt;code&gt;pformat()&lt;/code&gt; function that returns a string, in case you had to do something other than printing it.&lt;/p&gt;
&lt;p&gt;Surprisingly, the signature of &lt;code&gt;pprint()&lt;/code&gt; is nothing like the &lt;code&gt;print()&lt;/code&gt; function&amp;rsquo;s one. You can&amp;rsquo;t even pass more than one positional argument, which shows how much it focuses on printing data structures.&lt;/p&gt;
&lt;h3 id=&quot;adding-colors-with-ansi-escape-sequences&quot;&gt;Adding Colors With ANSI Escape Sequences&lt;/h3&gt;
&lt;p&gt;As personal computers got more sophisticated, they had better graphics and could display more colors. However, different vendors had their own idea about the API design for controlling it. That changed a few decades ago when people at the American National Standards Institute decided to unify it by defining &lt;a href=&quot;https://en.wikipedia.org/wiki/ANSI_escape_code&quot;&gt;ANSI escape codes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Most of today&amp;rsquo;s terminal emulators support this standard to some degree. Until recently, the Windows operating system was a notable exception. Therefore, if you want the best portability, use the &lt;a href=&quot;https://pypi.org/project/colorama/&quot;&gt;&lt;code&gt;colorama&lt;/code&gt;&lt;/a&gt; library in Python. It translates ANSI codes to their appropriate counterparts in Windows while keeping them intact in other operating systems.&lt;/p&gt;
&lt;p&gt;To check if your terminal understands a subset of the ANSI escape sequences, for example, related to colors, you can try using 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; tput colors
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;My default terminal on Linux says it can display 256 distinct colors, while xterm gives me only 8. The command would return a negative number if colors were unsupported.&lt;/p&gt;
&lt;p&gt;ANSI escape sequences are like a markup language for the terminal. In HTML you work with tags, such as &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt;, to change how elements look in the document. These tags are mixed with your content, but they&amp;rsquo;re not visible themselves. Similarly, escape codes won&amp;rsquo;t show up in the terminal as long as it recognizes them. Otherwise, they&amp;rsquo;ll appear in the literal form as if you were viewing the source of a website.&lt;/p&gt;
&lt;p&gt;As its name implies, a sequence must begin with the non-printable &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-escape&quot;&gt;Esc&lt;/kbd&gt;&lt;/span&gt; character, whose ASCII value is 27, sometimes denoted as &lt;code&gt;0x1b&lt;/code&gt; in hexadecimal or &lt;code&gt;033&lt;/code&gt; in octal. You may use Python number literals to quickly verify it&amp;rsquo;s indeed the same number:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x1b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0o33&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Additionally, you can obtain it with the &lt;code&gt;\e&lt;/code&gt; escape sequence in the shell:&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;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;\e&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The most common ANSI escape sequences take the following form:&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;Element&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-escape&quot;&gt;Esc&lt;/kbd&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;non-printable escape character&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\033&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;opening square bracket&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;numeric code&lt;/td&gt;
&lt;td&gt;one or more numbers separated with &lt;code&gt;;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;character code&lt;/td&gt;
&lt;td&gt;uppercase or lowercase letter&lt;/td&gt;
&lt;td&gt;&lt;code&gt;m&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;strong&gt;numeric code&lt;/strong&gt; can be one or more numbers separated with a semicolon, while the &lt;strong&gt;character code&lt;/strong&gt; is just one letter. Their specific meaning is defined by the ANSI standard. For example, to reset all formatting, you would type one of the following commands, which use the code zero and the letter &lt;code&gt;m&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;\e[0m&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;\x1b[0m&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;\033[0m&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At the other end of the spectrum, you have compound code values. To set foreground and background with RGB channels, given that your terminal supports 24-bit depth, you could provide multiple numbers:&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;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;\e[38;2;0;0;0m\e[48;2;255;255;255mBlack on white\e[0m&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s not just text color that you can set with the ANSI escape codes. You can, for example, clear and scroll the terminal window, change its background, move the cursor around, make the text blink or decorate it with an underline.&lt;/p&gt;
&lt;p&gt;In Python, you&amp;rsquo;d probably write a helper function to allow for wrapping arbitrary codes into a sequence:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;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;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\033&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{code}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;m&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;31;1;4&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;s1&quot;&gt;&amp;#39;really&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39; important&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This would make the word &lt;code&gt;really&lt;/code&gt; appear in red, bold, and underlined font:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/ansi.21ed85878eb9.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/ansi.21ed85878eb9.png&quot; width=&quot;576&quot; height=&quot;236&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/ansi.21ed85878eb9.png&amp;amp;w=144&amp;amp;sig=1b3e337786114c9e099a662d5e096ce1d41ba6a5 144w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/ansi.21ed85878eb9.png&amp;amp;w=288&amp;amp;sig=cb8720ce7fb4db092d674380ef3bf3543503546a 288w, https://files.realpython.com/media/ansi.21ed85878eb9.png 576w&quot; sizes=&quot;75vw&quot; alt=&quot;Text formatted with ANSI escape codes&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;However, there are higher-level abstractions over ANSI escape codes, such as the mentioned &lt;code&gt;colorama&lt;/code&gt; library, as well as tools for building user interfaces in the console.&lt;/p&gt;
&lt;h3 id=&quot;building-console-user-interfaces&quot;&gt;Building Console User Interfaces&lt;/h3&gt;
&lt;p&gt;While playing with ANSI escape codes is undeniably a ton of fun, in the real world you&amp;rsquo;d rather have more abstract building blocks to put together a user interface. There are a few libraries that provide such a high level of control over the terminal, but &lt;a href=&quot;https://docs.python.org/3/howto/curses.html&quot;&gt;&lt;code&gt;curses&lt;/code&gt;&lt;/a&gt; seems to be the most popular choice.&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; To use the &lt;code&gt;curses&lt;/code&gt; library in Windows, you need to install a third-party package:&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;C:\&amp;gt; pip install windows-curses&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s because &lt;code&gt;curses&lt;/code&gt; isn&amp;rsquo;t available in the standard library of the Python distribution for Windows.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Primarily, it allows you to think in terms of independent graphical widgets instead of a blob of text. Besides, you get a lot of freedom in expressing your inner artist, because it&amp;rsquo;s really like painting a blank canvas. The library hides the complexities of having to deal with different terminals. Other than that, it has great support for keyboard events, which might be useful for writing video games.&lt;/p&gt;
&lt;p&gt;How about making a retro snake game? Let&amp;rsquo;s create a Python snake simulator:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/snake.a9589582b58a.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/snake.a9589582b58a.gif&quot; width=&quot;576&quot; height=&quot;392&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/snake.a9589582b58a.gif&amp;amp;w=144&amp;amp;sig=a02bac6a4123b5c1a10112973045e6deec2895c3 144w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/snake.a9589582b58a.gif&amp;amp;w=288&amp;amp;sig=0019bb69f00b55d6201acf7661b870f865758f61 288w, https://files.realpython.com/media/snake.a9589582b58a.gif 576w&quot; sizes=&quot;75vw&quot; alt=&quot;The retro snake game built with curses library&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;First, you need to import the &lt;code&gt;curses&lt;/code&gt; module. Since it modifies the state of a running terminal, it&amp;rsquo;s important to handle errors and gracefully restore the previous state. You can do this manually, but the library comes with a convenient wrapper for your main 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;curses&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;screen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrapper&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;Note, the function must accept a reference to the screen object, also known as &lt;code&gt;stdscr&lt;/code&gt;, that you&amp;rsquo;ll use later for additional setup.&lt;/p&gt;
&lt;p&gt;If you run this program now, you won&amp;rsquo;t see any effects, because it terminates immediately. However, you can add a small delay to have a sneak peek:&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;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;curses&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;screen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrapper&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 time the screen went completely blank for a second, but the cursor was still blinking. To hide it, just call one of the configuration functions defined in the module:&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;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;curses&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;screen&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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curs_set&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;# Hide the cursor&lt;/span&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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrapper&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;Let&amp;rsquo;s define the snake as a list of points in screen coordinates:&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;snake&lt;/span&gt; &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;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The head of the snake is always the first element in the list, whereas the tail is the last one. The initial shape of the snake is horizontal, starting from the top-left corner of the screen and facing to the right. While its y-coordinate stays at zero, its x-coordinate decreases from head to tail.&lt;/p&gt;
&lt;p&gt;To draw the snake, you&amp;rsquo;ll start with the head and then follow with the remaining segments. Each segment carries &lt;code&gt;(y, x)&lt;/code&gt; coordinates, so you can unpack them:&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 the snake&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addstr&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;snake&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;@&amp;#39;&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;segment&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snake&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;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addstr&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;segment&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;Again, if you run this code now, it won&amp;rsquo;t display anything, because you must explicitly refresh the screen afterward:&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;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;curses&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;screen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curs_set&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;# Hide the cursor&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;snake&lt;/span&gt; &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;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Draw the snake&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addstr&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;snake&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;@&amp;#39;&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;segment&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snake&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;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addstr&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;segment&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;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refresh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrapper&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;You want to move the snake in one of four directions, which can be defined as vectors. Eventually, the direction will change in response to an arrow keystroke, so you may hook it up to the library&amp;rsquo;s key codes:&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;directions&lt;/span&gt; &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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_UP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;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;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_DOWN&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;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_LEFT&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;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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_RIGHT&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;p&quot;&gt;}&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;n&quot;&gt;directions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_RIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;How does a snake move? It turns out that only its head really moves to a new location, while all other segments shift towards it. In each step, almost all segments remain the same, except for the head and the tail. Assuming the snake isn&amp;rsquo;t growing, you can remove the tail and insert a new head at the beginning of the list:&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;# Move the snake&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;snake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;snake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tuple&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;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;snake&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;direction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To get the new coordinates of the head, you need to add the direction vector to it. However, adding tuples in Python results in a bigger tuple instead of the algebraic sum of the corresponding vector components. One way to fix this is by using the built-in &lt;code&gt;zip()&lt;/code&gt;, &lt;code&gt;sum()&lt;/code&gt;, and &lt;code&gt;map()&lt;/code&gt; functions.&lt;/p&gt;
&lt;p&gt;The direction will change on a keystroke, so you need to call &lt;code&gt;.getch()&lt;/code&gt; to obtain the pressed key code. However, if the pressed key doesn&amp;rsquo;t correspond to the arrow keys defined earlier as dictionary keys, the direction won&amp;rsquo;t change:&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;# Change direction on arrow keystroke&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;n&quot;&gt;directions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getch&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default, however, &lt;code&gt;.getch()&lt;/code&gt; is a blocking call that would prevent the snake from moving unless there was a keystroke. Therefore, you need to make the call non-blocking by adding yet another configuration:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curs_set&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;# Hide the cursor&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nodelay&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;c1&quot;&gt;# Don&amp;#39;t block I/O calls&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;re almost done, but there&amp;rsquo;s just one last thing left. If you now loop this code, the snake will appear to be growing instead of moving. That&amp;rsquo;s because you have to erase the screen explicitly before each iteration.&lt;/p&gt;
&lt;p&gt;Finally, this is all you need to play the snake game in Python:&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;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;curses&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;screen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curs_set&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;# Hide the cursor&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nodelay&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;c1&quot;&gt;# Don&amp;#39;t block I/O calls&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;directions&lt;/span&gt; &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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_UP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;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;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_DOWN&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;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_LEFT&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;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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_RIGHT&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;p&quot;&gt;}&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;n&quot;&gt;directions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_RIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;snake&lt;/span&gt; &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;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&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;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;erase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Draw the snake&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addstr&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;snake&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;@&amp;#39;&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;segment&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snake&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;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addstr&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;segment&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;c1&quot;&gt;# Move the snake&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;snake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;snake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tuple&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;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;snake&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;direction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Change direction on arrow keystroke&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;n&quot;&gt;directions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getch&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;screen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refresh&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;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;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;curses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrapper&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 is merely scratching the surface of the possibilities that the &lt;code&gt;curses&lt;/code&gt; module opens up. You may use it for game development like this or more business-oriented applications.&lt;/p&gt;
&lt;h3 id=&quot;living-it-up-with-cool-animations&quot;&gt;Living It Up With Cool Animations&lt;/h3&gt;
&lt;p&gt;Not only can animations make the user interface more appealing to the eye, but they also improve the overall user experience. When you provide early feedback to the user, for example, they&amp;rsquo;ll know if your program&amp;rsquo;s still working or if it&amp;rsquo;s time to kill it.&lt;/p&gt;
&lt;p&gt;To animate text in the terminal, you have to be able to freely move the cursor around. You can do this with one of the tools mentioned previously, that is ANSI escape codes or the &lt;code&gt;curses&lt;/code&gt; library. However, I&amp;rsquo;d like to show you an even simpler way.&lt;/p&gt;
&lt;p&gt;If the animation can be constrained to a single line of text, then you might be interested in two special escape character sequences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Carriage return:&lt;/strong&gt; &lt;code&gt;\r&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backspace:&lt;/strong&gt; &lt;code&gt;\b&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first one moves the cursor to the beginning of the line, whereas the second one moves it only one character to the left. They both work in a non-destructive way without overwriting text that&amp;rsquo;s already been written.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at a few examples.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll often want to display some kind of a &lt;strong&gt;spinning wheel&lt;/strong&gt; to indicate a work in progress without knowing exactly how much time&amp;rsquo;s left to finish:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/spinning_wheel.c595af6f83ea.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/spinning_wheel.c595af6f83ea.gif&quot; width=&quot;576&quot; height=&quot;236&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spinning_wheel.c595af6f83ea.gif&amp;amp;w=144&amp;amp;sig=6668f7484a9d15711f5a9f149647b38baf8683cb 144w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/spinning_wheel.c595af6f83ea.gif&amp;amp;w=288&amp;amp;sig=267bb31016ff764a987006dcecafcf80233af3ad 288w, https://files.realpython.com/media/spinning_wheel.c595af6f83ea.gif 576w&quot; sizes=&quot;75vw&quot; alt=&quot;Indefinite animation in the terminal&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Many command line tools use this trick while downloading data over the network. You can make a really simple stop motion animation from a sequence of characters that will cycle in a round-robin fashion:&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;itertools&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cycle&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cycle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;r&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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r&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;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flush&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;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The loop gets the next character to print, then moves the cursor to the beginning of the line, and overwrites whatever there was before without adding a newline. You don&amp;rsquo;t want extra space between positional arguments, so separator argument must be blank. Also, notice the use of Python&amp;rsquo;s raw strings due to backslash characters present in the literal.&lt;/p&gt;
&lt;p&gt;When you know the remaining time or task completion percentage, then you&amp;rsquo;re able to show an animated progress bar:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/progress.6bd055d8dcc4.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/progress.6bd055d8dcc4.gif&quot; width=&quot;576&quot; height=&quot;236&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/progress.6bd055d8dcc4.gif&amp;amp;w=144&amp;amp;sig=b77d52a79d28329d6ec8d5e43fbffd8bc112896e 144w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/progress.6bd055d8dcc4.gif&amp;amp;w=288&amp;amp;sig=57b015e2b6a7534b9a9d027d81a71b52967c20e0 288w, https://files.realpython.com/media/progress.6bd055d8dcc4.gif 576w&quot; sizes=&quot;75vw&quot; alt=&quot;Progress bar animation in the terminal&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;First, you need to calculate how many hashtags to display and how many blank spaces to insert. Next, you erase the line and build the bar from scratch:&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;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;percent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;percent&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;n&quot;&gt;right&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;left&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r&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;s1&quot;&gt;&amp;#39;#&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&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;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&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;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;{percent:.0f}&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;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;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;101&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;progress&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;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;As before, each request for update repaints the entire line.&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&amp;rsquo;s a feature-rich &lt;a href=&quot;https://pypi.org/project/progressbar2/&quot;&gt;&lt;code&gt;progressbar2&lt;/code&gt;&lt;/a&gt; library, along with a few other similar tools, that can show progress in a much more comprehensive way.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;making-sounds-with-print&quot;&gt;Making Sounds With Print&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re old enough to remember computers with a PC speaker, then you must also remember their distinctive &lt;em&gt;beep&lt;/em&gt; sound, often used to indicate hardware problems. They could barely make any more noises than that, yet video games seemed so much better with it.&lt;/p&gt;
&lt;p&gt;Today you can still take advantage of this small loudspeaker, but chances are your laptop didn&amp;rsquo;t come with one. In such a case, you can enable &lt;strong&gt;terminal bell&lt;/strong&gt; emulation in your shell, so that a system warning sound is played instead.&lt;/p&gt;
&lt;p&gt;Go ahead and type this command to see if your terminal can play a sound:&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;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;\a&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This would normally print text, but the &lt;code&gt;-e&lt;/code&gt; flag enables the interpretation of backslash escapes. As you can see, there&amp;rsquo;s a dedicated escape sequence &lt;code&gt;\a&lt;/code&gt;, which stands for &amp;ldquo;alert&amp;rdquo;, that outputs a special &lt;a href=&quot;https://en.wikipedia.org/wiki/Bell_character&quot;&gt;bell character&lt;/a&gt;. Some terminals make a sound whenever they see it.&lt;/p&gt;
&lt;p&gt;Similarly, you can print this character in Python. Perhaps in a loop to form some kind of melody. While it&amp;rsquo;s only a single note, you can still vary the length of pauses between consecutive instances. That seems like a perfect toy for Morse code playback!&lt;/p&gt;
&lt;p&gt;The rules are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Letters are encoded with a sequence of &lt;strong&gt;dot&lt;/strong&gt; (&amp;middot;) and &lt;strong&gt;dash&lt;/strong&gt; (&amp;ndash;) symbols.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;dot&lt;/strong&gt; is one unit of time.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;dash&lt;/strong&gt; is three units of time.&lt;/li&gt;
&lt;li&gt;Individual &lt;strong&gt;symbols&lt;/strong&gt; in a letter are spaced one unit of time apart.&lt;/li&gt;
&lt;li&gt;Symbols of two adjacent &lt;strong&gt;letters&lt;/strong&gt; are spaced three units of time apart.&lt;/li&gt;
&lt;li&gt;Symbols of two adjacent &lt;strong&gt;words&lt;/strong&gt; are spaced seven units of time apart.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;According to those rules, you could be &amp;ldquo;printing&amp;rdquo; an SOS signal indefinitely in the following 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;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;dot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;symbol_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;symbol_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;letter_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;symbol_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;symbol_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;letter_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;symbol_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;symbol_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;word_space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Python, you can implement it in merely ten lines of code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;speed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbol&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;duration&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;symbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flush&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;dot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;speed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;·&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\a&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;n&quot;&gt;dash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;speed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;−&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\a&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;n&quot;&gt;symbol_space&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;speed&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;n&quot;&gt;letter_space&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;speed&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;n&quot;&gt;word_space&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;speed&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;Maybe you could even take it one step further and make a command line tool for translating text into Morse code? Either way, I hope you&amp;rsquo;re having fun with this!&lt;/p&gt;
&lt;h2 id=&quot;mocking-python-print-in-unit-tests&quot;&gt;Mocking Python Print in Unit Tests&lt;/h2&gt;
&lt;p&gt;Nowadays, it&amp;rsquo;s expected that you ship code that meets high quality standards. If you aspire to become a professional, you must learn &lt;a href=&quot;https://realpython.com/python-testing/&quot;&gt;how to test&lt;/a&gt; your code.&lt;/p&gt;
&lt;p&gt;Software testing is especially important in dynamically typed languages, such as  Python, which don&amp;rsquo;t have a compiler to warn you about obvious mistakes. Defects can make their way to the production environment and remain dormant for a long time, until that one day when a branch of code finally gets executed.&lt;/p&gt;
&lt;p&gt;Sure, you have &lt;a href=&quot;https://realpython.com/python-code-quality/#linters&quot;&gt;linters&lt;/a&gt;, &lt;a href=&quot;https://realpython.com/python-type-checking/&quot;&gt;type checkers&lt;/a&gt;, and other tools for static code analysis to assist you. But they won&amp;rsquo;t tell you whether your program does what it&amp;rsquo;s supposed to do on the business level.&lt;/p&gt;
&lt;p&gt;So, should you be testing &lt;code&gt;print()&lt;/code&gt;? No. After all, it&amp;rsquo;s a built-in function that must have already gone through a comprehensive suite of tests.  What you want to test, though, is whether your code is calling &lt;code&gt;print()&lt;/code&gt; at the right time with the expected parameters. That&amp;rsquo;s known as a &lt;strong&gt;behavior&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You can test behaviors by &lt;a href=&quot;https://realpython.com/python-mock-library/&quot;&gt;mocking&lt;/a&gt; real objects or functions. In this case, you want to mock &lt;code&gt;print()&lt;/code&gt; to record and verify its invocations.&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 might have heard the terms: &lt;strong&gt;dummy&lt;/strong&gt;, &lt;strong&gt;fake&lt;/strong&gt;, &lt;strong&gt;stub&lt;/strong&gt;, &lt;strong&gt;spy&lt;/strong&gt;, or &lt;strong&gt;mock&lt;/strong&gt; used interchangeably. Some people make a distinction between them, while others don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;Martin Fowler explains their differences in a &lt;a href=&quot;https://martinfowler.com/bliki/TestDouble.html&quot;&gt;short glossary&lt;/a&gt; and collectively calls them &lt;strong&gt;test doubles&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Mocking in Python can be done twofold. First, you can take the traditional path of statically-typed languages by employing dependency injection. This may sometimes require you to change the code under test, which isn&amp;rsquo;t always possible if the code is defined in an external library:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;download&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;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&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;log&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;Downloading &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;# ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the same example I used in an earlier section to talk about function composition. It basically allows for substituting &lt;code&gt;print()&lt;/code&gt; with a custom function of the same interface. To check if it prints the right message, you have to intercept it by injecting a mocked 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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mock_print&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;mock_print&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;
&lt;span class=&quot;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;download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;resource&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock_print&lt;/span&gt;&lt;span class=&quot;p&quot;&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;assert&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Downloading resource&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock_print&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_message&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Calling this mock makes it save the last message in an attribute, which you can inspect later, for example in an &lt;code&gt;assert&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;In a slightly alternative solution, instead of replacing the entire &lt;code&gt;print()&lt;/code&gt; function with a custom wrapper, you could redirect the standard output to an in-memory file-like stream of characters:&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;download&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;n&quot;&gt;stream&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Downloading &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;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;c1&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memory_buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StringIO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;app.js&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;style.css&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memory_buffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Downloading app.js\nDownloading style.css\n&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This time the function explicitly calls &lt;code&gt;print()&lt;/code&gt;, but it exposes its &lt;code&gt;file&lt;/code&gt; parameter to the outside world.&lt;/p&gt;
&lt;p&gt;However, a more Pythonic way of mocking objects takes advantage of the built-in &lt;code&gt;mock&lt;/code&gt; module, which uses a technique called &lt;a href=&quot;https://en.wikipedia.org/wiki/Monkey_patch&quot;&gt;monkey patching&lt;/a&gt;. This derogatory name stems from it being a &amp;ldquo;dirty hack&amp;rdquo; that you can easily shoot yourself in the foot with. It&amp;rsquo;s less elegant than dependency injection but definitely quick and convenient.&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;code&gt;mock&lt;/code&gt; module got absorbed by the standard library in Python 3, but before that, it was a third-party package. You had to install it separately:&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; pip2 install mock
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Other than that, you referred to it as &lt;code&gt;mock&lt;/code&gt;, whereas in Python 3 it&amp;rsquo;s part of the unit testing module, so you must import from &lt;code&gt;unittest.mock&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;What monkey patching does is alter implementation dynamically at runtime. Such a change is visible globally, so it may have unwanted consequences. In practice, however, patching only affects the code for the duration of test execution.&lt;/p&gt;
&lt;p&gt;To mock &lt;code&gt;print()&lt;/code&gt; in a test case, you&amp;rsquo;ll typically use the &lt;code&gt;@patch&lt;/code&gt; &lt;a href=&quot;https://realpython.com/primer-on-python-decorators/&quot;&gt;decorator&lt;/a&gt; and specify a target for patching by referring to it with a fully qualified name, that is including the module name:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;unittest.mock&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patch&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;builtins.print&amp;#39;&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;test_print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mock_print&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;not a real print&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mock_print&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assert_called_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;not a real print&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will automatically create the mock for you and inject it to the test function.  However, you need to declare that your test function accepts a mock now. The underlying mock object has lots of useful methods and attributes for verifying behavior.&lt;/p&gt;
&lt;p&gt;Did you notice anything peculiar about that code snippet?&lt;/p&gt;
&lt;p&gt;Despite injecting a mock to the function, you&amp;rsquo;re not calling it directly, although you could. That injected mock is only used to make assertions afterward and maybe to prepare the context before running the test.&lt;/p&gt;
&lt;p&gt;In real life, mocking helps to isolate the code under test by removing dependencies such as a database connection. You rarely call mocks in a test, because that doesn&amp;rsquo;t make much sense. Rather, it&amp;rsquo;s other pieces of code that call your mock indirectly without knowing it.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what that means:&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;unittest.mock&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patch&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;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;Hello, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{name}&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;nd&quot;&gt;@patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;builtins.print&amp;#39;&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;test_greet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mock_print&lt;/span&gt;&lt;span class=&quot;p&quot;&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;s1&quot;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mock_print&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assert_called_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello, John!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code under test is a function that prints a greeting. Even though it&amp;rsquo;s a fairly simple function, you can&amp;rsquo;t test it easily because it doesn&amp;rsquo;t return a value. It has a side-effect.&lt;/p&gt;
&lt;p&gt;To eliminate that side-effect, you need to mock the dependency out. Patching lets you avoid making changes to the original function, which can remain agnostic about &lt;code&gt;print()&lt;/code&gt;. It thinks it&amp;rsquo;s calling &lt;code&gt;print()&lt;/code&gt;, but in reality, it&amp;rsquo;s calling a mock you&amp;rsquo;re in total control of.&lt;/p&gt;
&lt;p&gt;There are many reasons for testing software. One of them is looking for bugs. When you write tests, you often want to get rid of the &lt;code&gt;print()&lt;/code&gt; function, for example, by mocking it away. Paradoxically, however, that same function can help you find bugs during a related process of debugging you&amp;rsquo;ll read about in the next section.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card841486&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;#collapse841486&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse841486&quot;&gt;Syntax in Python 2&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse841486&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse841486&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse841486&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card841486&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;You can&amp;rsquo;t monkey patch the &lt;code&gt;print&lt;/code&gt; statement in Python 2, nor can you inject it as a dependency. However, you have a few other options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use stream redirection.&lt;/li&gt;
&lt;li&gt;Patch the standard output defined in the &lt;code&gt;sys&lt;/code&gt; module.&lt;/li&gt;
&lt;li&gt;Import &lt;code&gt;print()&lt;/code&gt; from the &lt;code&gt;__future__&lt;/code&gt; module.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s examine them one by one.&lt;/p&gt;
&lt;p&gt;Stream redirection is almost identical to the example you saw earlier:&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;download&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;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&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;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Downloading &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;c1&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;StringIO&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringIO&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memory_buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringIO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;app.js&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;style.css&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memory_buffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Downloading app.js\nDownloading style.css\n&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are only two differences. First, the syntax for stream redirection uses chevron (&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;) instead of the &lt;code&gt;file&lt;/code&gt; argument. The other difference is where &lt;code&gt;StringIO&lt;/code&gt; is defined. You can import it from a similarly named &lt;code&gt;StringIO&lt;/code&gt; module, or &lt;code&gt;cStringIO&lt;/code&gt; for a faster implementation.&lt;/p&gt;
&lt;p&gt;Patching the standard output from the &lt;code&gt;sys&lt;/code&gt; module is exactly what it sounds like, but you need to be aware of a few gotchas:&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;mock&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&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;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;!&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;sys.stdout&amp;#39;&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;test_greet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mock_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&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;s1&quot;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mock_stdout&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assert_has_calls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello, John!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;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;First of all, remember to install the &lt;code&gt;mock&lt;/code&gt; module as it wasn&amp;rsquo;t available in the standard library in Python 2.&lt;/p&gt;
&lt;p&gt;Secondly, the &lt;code&gt;print&lt;/code&gt; statement calls the underlying &lt;code&gt;.write()&lt;/code&gt; method on the mocked object instead of calling the object itself. That&amp;rsquo;s why you&amp;rsquo;ll run assertions against &lt;code&gt;mock_stdout.write&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Finally, a single &lt;code&gt;print&lt;/code&gt; statement doesn&amp;rsquo;t always correspond to a single call to &lt;code&gt;sys.stdout.write()&lt;/code&gt;. In fact, you&amp;rsquo;ll see the newline character written separately.&lt;/p&gt;
&lt;p&gt;The last option you have is importing  &lt;code&gt;print()&lt;/code&gt; from &lt;code&gt;future&lt;/code&gt; and patching it:&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;__future__&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;print_function&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;mock&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patch&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;k&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, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;!&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;__builtin__.print&amp;#39;&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;test_greet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mock_print&lt;/span&gt;&lt;span class=&quot;p&quot;&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;s1&quot;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mock_print&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assert_called_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello, John!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Again, it&amp;rsquo;s nearly identical to Python 3, but the &lt;code&gt;print()&lt;/code&gt; function is defined in the &lt;code&gt;__builtin__&lt;/code&gt; module rather than &lt;code&gt;builtins&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h2 id=&quot;print-debugging&quot;&gt;Print Debugging&lt;/h2&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll take a look at the available tools for debugging in Python, starting from a humble &lt;code&gt;print()&lt;/code&gt; function, through the &lt;code&gt;logging&lt;/code&gt; module, to a fully fledged debugger. After reading it, you&amp;rsquo;ll be able to make an educated decision about which of them is the most suitable in a given situation.&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; Debugging is the process of looking for the root causes of &lt;strong&gt;bugs&lt;/strong&gt; or defects in software after they&amp;rsquo;ve been discovered, as well as taking steps to fix them.&lt;/p&gt;
&lt;p&gt;The term &lt;strong&gt;bug&lt;/strong&gt; has an &lt;a href=&quot;https://en.wikipedia.org/wiki/Debugging#Origin_of_the_term&quot;&gt;amusing story&lt;/a&gt; about the origin of its name.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;tracing&quot;&gt;Tracing&lt;/h3&gt;
&lt;p&gt;Also known as &lt;strong&gt;print debugging&lt;/strong&gt; or &lt;strong&gt;caveman debugging&lt;/strong&gt;, it&amp;rsquo;s the most basic form of debugging. While a little bit old-fashioned, it&amp;rsquo;s still powerful and has its uses.&lt;/p&gt;
&lt;p&gt;The idea is to follow the path of program execution until it stops abruptly, or gives incorrect results, to identify the exact instruction with a problem. You do that by inserting print statements with words that stand out in carefully chosen places.&lt;/p&gt;
&lt;p&gt;Take a look at this example, which manifests a rounding error:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;average&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &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;debug1:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&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;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;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;debug2:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&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;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&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;mf&quot;&gt;0.1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;average&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;o&quot;&gt;*&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;span class=&quot;go&quot;&gt;debug1: [0.1, 0.1, 0.1]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;debug2: 0.30000000000000004&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the function doesn&amp;rsquo;t return the expected value of &lt;code&gt;0.1&lt;/code&gt;, but now you know it&amp;rsquo;s because the sum is a little off. Tracing the state of variables at different steps of the algorithm can give you a hint where the issue is.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardab3ddc&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;#collapseab3ddc&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapseab3ddc&quot;&gt;Rounding Error&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapseab3ddc&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapseab3ddc&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapseab3ddc&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardab3ddc&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;In this case, the problem lies in how &lt;strong&gt;floating point&lt;/strong&gt; numbers are represented in computer memory. Remember that numbers are stored in binary form. Decimal value of &lt;code&gt;0.1&lt;/code&gt; turns out to have an infinite binary representation, which gets rounded.&lt;/p&gt;
&lt;p&gt;For more information on rounding numbers in Python, you can check out &lt;a href=&quot;https://realpython.com/python-rounding/&quot;&gt;How to Round Numbers in Python&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;This method is simple and intuitive and will work in pretty much every programming language out there. Not to mention, it&amp;rsquo;s a great exercise in the learning process.&lt;/p&gt;
&lt;p&gt;On the other hand, once you master more advanced techniques, it&amp;rsquo;s hard to go back, because they allow you to find bugs much quicker. Tracing is a laborious manual process, which can let even more errors slip through. The build and deploy cycle takes time. Afterward, you need to remember to meticulously remove all the &lt;code&gt;print()&lt;/code&gt; calls you made without accidentally touching the genuine ones.&lt;/p&gt;
&lt;p&gt;Besides, it requires you to make changes in the code, which isn&amp;rsquo;t always possible. Maybe you&amp;rsquo;re debugging an application running in a remote web server or want to diagnose a problem in a &lt;strong&gt;post-mortem&lt;/strong&gt; fashion. Sometimes you simply don&amp;rsquo;t have access to the standard output.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s precisely where &lt;a href=&quot;https://realpython.com/courses/logging-python/&quot;&gt;logging&lt;/a&gt; shines.&lt;/p&gt;
&lt;h3 id=&quot;logging&quot;&gt;Logging&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s pretend for a minute that you&amp;rsquo;re running an e-commerce website. One day, an angry customer makes a phone call complaining about a failed transaction and saying he lost his money. He claims to have tried purchasing a few items, but in the end, there was some cryptic error that prevented him from finishing that order. Yet, when he checked his bank account, the money was gone.&lt;/p&gt;
&lt;p&gt;You apologize sincerely and make a refund, but also don&amp;rsquo;t want this to happen again in the future. How do you debug that? If only you had some trace of what happened, ideally in the form of a chronological list of events with their context.&lt;/p&gt;
&lt;p&gt;Whenever you find yourself doing print debugging, consider turning it into permanent log messages. This may help in situations like this, when you need to analyze a problem after it happened, in an environment that you don&amp;rsquo;t have access to.&lt;/p&gt;
&lt;p&gt;There are sophisticated tools for log aggregation and searching, but at the most basic level, you can think of logs as text files. Each line conveys detailed information about an event in your system. Usually, it won&amp;rsquo;t contain personally identifying information, though, in some cases, it may be mandated by law.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a breakdown of a typical log record:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;[2019-06-14 15:18:34,517][DEBUG][root][MainThread] Customer(id=123) logged out
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, it has a structured form. Apart from a descriptive message, there are a few customizable fields, which provide the context of an event. Here, you have the exact date and time, the log level, the logger name, and the thread name.&lt;/p&gt;
&lt;p&gt;Log levels allow you to filter messages quickly to reduce noise. If you&amp;rsquo;re looking for an error, you don&amp;rsquo;t want to see all the warnings or debug messages, for example. It&amp;rsquo;s trivial to disable or enable messages at certain log levels through the configuration, without even touching the code.&lt;/p&gt;
&lt;p&gt;With logging, you can keep your debug messages separate from the standard output. All the log messages go to the standard error stream by default, which can conveniently show up in different colors. However, you can redirect log messages to separate files, even for individual modules!&lt;/p&gt;
&lt;p&gt;Quite commonly, misconfigured logging can lead to running out of space on the server&amp;rsquo;s disk. To prevent that, you may set up &lt;strong&gt;log rotation&lt;/strong&gt;, which will keep the log files for a specified duration, such as one week, or once they hit a certain size. Nevertheless, it&amp;rsquo;s always a good practice to archive older logs. Some regulations enforce that customer data be kept for as long as five years!&lt;/p&gt;
&lt;p&gt;Compared to other programming languages, &lt;a href=&quot;https://realpython.com/python-logging/&quot;&gt;logging in Python&lt;/a&gt; is simpler, because the &lt;code&gt;logging&lt;/code&gt; module is bundled with the standard library. You just import and configure it in as little as two lines of code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;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;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can call functions defined at the module level, which are hooked to the &lt;strong&gt;root logger&lt;/strong&gt;, but more the common practice is to obtain a dedicated logger for each of your source files:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&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;c1&quot;&gt;# Module-level function&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&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;c1&quot;&gt;# Logger&amp;#39;s method&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The advantage of using custom loggers is more fine-grain control. They&amp;rsquo;re usually named after the module they were defined in through the &lt;code&gt;__name__&lt;/code&gt; variable.&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&amp;rsquo;s a somewhat related &lt;code&gt;warnings&lt;/code&gt; module in Python, which can also log messages to the standard error stream. However, it has a narrower spectrum of applications, mostly in library code, whereas client applications should use the &lt;code&gt;logging&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;That said, you can make them work together by calling &lt;code&gt;logging.captureWarnings(True)&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;One last reason to switch from the &lt;code&gt;print()&lt;/code&gt; function to logging is thread safety. In the upcoming section, you&amp;rsquo;ll see that the former doesn&amp;rsquo;t play well with multiple threads of execution.&lt;/p&gt;
&lt;h3 id=&quot;debugging&quot;&gt;Debugging&lt;/h3&gt;
&lt;p&gt;The truth is that neither tracing nor logging can be considered real debugging. To do actual debugging, you need a debugger tool, which allows you to do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Step through the code interactively.&lt;/li&gt;
&lt;li&gt;Set breakpoints, including conditional breakpoints.&lt;/li&gt;
&lt;li&gt;Introspect variables in memory.&lt;/li&gt;
&lt;li&gt;Evaluate custom expressions at runtime.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A crude debugger that runs in the terminal, unsurprisingly named &lt;strong&gt;&lt;code&gt;pdb&lt;/code&gt;&lt;/strong&gt; for &amp;ldquo;The Python Debugger,&amp;rdquo; is distributed as part of the standard library. This makes it always available, so it may be your only choice for performing remote debugging. Perhaps that&amp;rsquo;s a good reason to get familiar with it.&lt;/p&gt;
&lt;p&gt;However, it doesn&amp;rsquo;t come with a graphical interface, so &lt;a href=&quot;https://realpython.com/python-debugging-pdb/&quot;&gt;using &lt;code&gt;pdb&lt;/code&gt;&lt;/a&gt; may be a bit tricky. If you can&amp;rsquo;t edit the code, you have to run it as a module and pass your script&amp;rsquo;s location:&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 pdb my_script.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Otherwise, you can set up a breakpoint directly in the code, which will pause the execution of your script and drop you into the debugger. The old way of doing this required two steps:&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;pdb&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_trace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;--Return--&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; &amp;lt;stdin&amp;gt;(1)&amp;lt;module&amp;gt;()-&amp;gt;None&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This shows up an interactive prompt, which might look intimidating at first. However, you can still type native Python at this point to examine or modify the state of local variables. Apart from that, there&amp;rsquo;s really only a handful of debugger-specific commands that you want to use for stepping through the code.&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; It&amp;rsquo;s customary to put the two instructions for spinning up a debugger on a single line. This requires the use of a semicolon, which is rarely found in Python programs:&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;pdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_trace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While certainly not Pythonic, it stands out as a reminder to remove it after you&amp;rsquo;re done with debugging.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Since Python 3.7, you can also call the built-in &lt;code&gt;breakpoint()&lt;/code&gt; function, which does the same thing, but in a more compact way and with some additional &lt;a href=&quot;https://realpython.com/python37-new-features/#the-breakpoint-built-in&quot;&gt;bells and whistles&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;average&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&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;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;breakpoint&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;k&quot;&gt;return&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;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;re probably going to use a visual debugger integrated with a code editor for the most part. &lt;a href=&quot;https://www.jetbrains.com/pycharm/&quot;&gt;PyCharm&lt;/a&gt; has an excellent debugger, which boasts high performance, but you&amp;rsquo;ll find &lt;a href=&quot;https://realpython.com/python-ides-code-editors-guide/&quot;&gt;plenty of alternative IDEs&lt;/a&gt; with debuggers, both paid and free of charge.&lt;/p&gt;
&lt;p&gt;Debugging isn&amp;rsquo;t the proverbial silver bullet. Sometimes logging or tracing will be a better solution. For example, defects that are hard to reproduce, such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Race_condition&quot;&gt;race conditions&lt;/a&gt;, often result from temporal coupling. When you stop at a breakpoint, that little pause in program execution may mask the problem. It&amp;rsquo;s kind of like the &lt;a href=&quot;https://en.wikipedia.org/wiki/Uncertainty_principle&quot;&gt;Heisenberg principle&lt;/a&gt;: you can&amp;rsquo;t measure and observe a bug at the same time.&lt;/p&gt;
&lt;p&gt;These methods aren&amp;rsquo;t mutually exclusive. They complement each other.&lt;/p&gt;
&lt;h2 id=&quot;thread-safe-printing&quot;&gt;Thread-Safe Printing&lt;/h2&gt;
&lt;p&gt;I briefly touched upon the thread safety issue before, recommending &lt;code&gt;logging&lt;/code&gt; over the &lt;code&gt;print()&lt;/code&gt; function. If you&amp;rsquo;re still reading this, then you must be comfortable with &lt;a href=&quot;https://realpython.com/intro-to-python-threading/&quot;&gt;the concept of threads&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thread safety means that a piece of code can be safely shared between multiple threads of execution. The simplest strategy for ensuring thread-safety is by sharing &lt;strong&gt;immutable&lt;/strong&gt; objects only. If threads can&amp;rsquo;t modify an object&amp;rsquo;s state, then there&amp;rsquo;s no risk of breaking its consistency.&lt;/p&gt;
&lt;p&gt;Another method takes advantage of &lt;strong&gt;local memory&lt;/strong&gt;, which makes each thread receive its own copy of the same object. That way, other threads can&amp;rsquo;t see the changes made to it in the current thread.&lt;/p&gt;
&lt;p&gt;But that doesn&amp;rsquo;t solve the problem, does it? You often want your threads to cooperate by being able to mutate a shared resource. The most common way of synchronizing concurrent access to such a resource is by &lt;strong&gt;locking&lt;/strong&gt; it. This gives exclusive write access to one or sometimes a few threads at a time.&lt;/p&gt;
&lt;p&gt;However, locking is expensive and reduces concurrent throughput, so other means for controlling access have been invented, such as &lt;strong&gt;atomic variables&lt;/strong&gt; or the &lt;strong&gt;compare-and-swap&lt;/strong&gt; algorithm.&lt;/p&gt;
&lt;p&gt;Printing isn&amp;rsquo;t thread-safe in Python. The &lt;code&gt;print()&lt;/code&gt; function holds a reference to the standard output, which is a shared global variable. In theory, because there&amp;rsquo;s no locking, a context switch could happen during a call to &lt;code&gt;sys.stdout.write()&lt;/code&gt;, intertwining bits of text from multiple &lt;code&gt;print()&lt;/code&gt; calls.&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 context switch means that one thread halts its execution, either voluntarily or not, so that another one can take over. This might happen at any moment, even in the middle of a function call.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In practice, however, that doesn&amp;rsquo;t happen. No matter how hard you try, writing to the standard output seems to be atomic. The only problem that you may sometimes observe is with messed up line breaks:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;[Thread-3 A][Thread-2 A][Thread-1 A]

[Thread-3 B][Thread-1 B]


[Thread-1 C][Thread-3 C]

[Thread-2 B]
[Thread-2 C]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To simulate this, you can increase the likelihood of a context switch by making the underlying &lt;code&gt;.write()&lt;/code&gt; method go to sleep for a random amount of time. How? By mocking it, which you already know about from an earlier section:&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;sys&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;threading&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_thread&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;unittest.mock&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patch&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;slow_write&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;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_thread&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;name&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;letter&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ABC&amp;#39;&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;{thread_name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{letter}&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;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;sys.stdout&amp;#39;&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;mock_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mock_stdout&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slow_write&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;3&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;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;task&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;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;First, you need to store the original &lt;code&gt;.write()&lt;/code&gt; method in a variable, which you&amp;rsquo;ll delegate to later. Then you provide your fake implementation, which will take up to one second to execute. Each thread will make a few &lt;code&gt;print()&lt;/code&gt; calls with its name and a letter: A, B, and C.&lt;/p&gt;
&lt;p&gt;If you read the mocking section before, then you may already have an idea of why printing misbehaves like that. Nonetheless, to make it crystal clear, you can capture values fed into your &lt;code&gt;slow_write()&lt;/code&gt; function. You&amp;rsquo;ll notice that you get a slightly different sequence each time:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-3 A]&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-2 A]&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-1 A]&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-3 B]&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;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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Even though &lt;code&gt;sys.stdout.write()&lt;/code&gt; itself is an atomic operation, a single call to the &lt;code&gt;print()&lt;/code&gt; function can yield more than one write. For example, line breaks are written separately from the rest of the text, and context switching takes place between those writes.&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 atomic nature of the standard output in Python is a byproduct of the &lt;a href=&quot;https://realpython.com/python-gil/&quot;&gt;Global Interpreter Lock&lt;/a&gt;, which applies locking around bytecode instructions. Be aware, however, that many interpreter flavors don&amp;rsquo;t have the GIL, where multi-threaded printing requires explicit locking.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can make the newline character become an integral part of the message by handling it manually:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;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;{thread_name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{letter}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will fix the output:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;[Thread-2 A]
[Thread-1 A]
[Thread-3 A]
[Thread-1 B]
[Thread-3 B]
[Thread-2 B]
[Thread-1 C]
[Thread-2 C]
[Thread-3 C]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice, however, that the &lt;code&gt;print()&lt;/code&gt; function still keeps making a separate call for the empty suffix, which translates to useless &lt;code&gt;sys.stdout.write(&#39;&#39;)&lt;/code&gt; instruction:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-2 A]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-1 A]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-3 A]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;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;&amp;#39;&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;[Thread-1 B]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;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;A truly thread-safe version of the &lt;code&gt;print()&lt;/code&gt; function could look like this:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;threading&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threading&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Lock&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;thread_safe_print&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;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can put that function in a module and import it elsewhere:&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;thread_safe_print&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thread_safe_print&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_thread&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;name&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;letter&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ABC&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;thread_safe_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;{thread_name}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{letter}&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, despite making two writes per each &lt;code&gt;print()&lt;/code&gt; request, only one thread is allowed to interact with the stream, while the rest must wait:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Lock acquired by Thread-3 &lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-3 A]&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Lock released by Thread-3&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Lock acquired by Thread-1&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;[Thread-1 B]&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Lock released by Thread-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;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;I added comments to indicate how the lock is limiting access to the shared resource.&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; Even in single-threaded code, you might get caught up in a similar situation. Specifically, when you&amp;rsquo;re printing to the standard output and the standard error streams at the same time. Unless you redirect one or both of them to separate files, they&amp;rsquo;ll both share a single terminal window.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Conversely, the &lt;code&gt;logging&lt;/code&gt; module is thread-safe by design, which is reflected by its ability to display thread names in the formatted message:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;basicConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(threadName)s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(message)s&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&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;go&quot;&gt;MainThread hello&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s another reason why you might not want to use the &lt;code&gt;print()&lt;/code&gt; function all the time.&lt;/p&gt;
&lt;h2 id=&quot;python-print-counterparts&quot;&gt;Python Print Counterparts&lt;/h2&gt;
&lt;p&gt;By now, you know a lot of what there is to know about &lt;code&gt;print()&lt;/code&gt;! The subject, however, wouldn&amp;rsquo;t be complete without talking about its counterparts a little bit. While &lt;code&gt;print()&lt;/code&gt; is about the output, there are functions and libraries for the input.&lt;/p&gt;
&lt;h3 id=&quot;built-in&quot;&gt;Built-In&lt;/h3&gt;
&lt;p&gt;Python comes with a built-in function for accepting input from the user, predictably called &lt;code&gt;input()&lt;/code&gt;. It accepts data from the standard input stream, which is usually the keyboard:&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;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Enter your name: &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Enter your name: jdoe&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;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;jdoe&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The function always returns a string, so you might need to parse it accordingly:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;How old are you? &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;ne&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The prompt parameter is completely optional, so nothing will show if you skip it, but the function will still work:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;hello world&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;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;hello world&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nevertheless, throwing in a descriptive call to action makes the user experience so much better.&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; To read from the standard input in Python 2, you have to call &lt;code&gt;raw_input()&lt;/code&gt; instead, which is yet another built-in. Unfortunately, there&amp;rsquo;s also a misleadingly named &lt;code&gt;input()&lt;/code&gt; function, which does a slightly different thing.&lt;/p&gt;
&lt;p&gt;In fact, it also takes the input from the standard stream, but then it tries to evaluate it as if it was Python code. Because that&amp;rsquo;s a potential &lt;strong&gt;security vulnerability&lt;/strong&gt;, this function was completely removed from Python 3, while &lt;code&gt;raw_input()&lt;/code&gt; got renamed to &lt;code&gt;input()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a quick comparison of the available functions and what they do:&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;Python 2&lt;/th&gt;
&lt;th&gt;Python 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;raw_input()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;input()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;input()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;eval(input())&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;As you can tell, it&amp;rsquo;s still possible to simulate the old behavior in Python 3.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Asking the user for a password with &lt;code&gt;input()&lt;/code&gt; is a bad idea because it&amp;rsquo;ll show up in plaintext as they&amp;rsquo;re typing it. In this case, you should be using the &lt;code&gt;getpass()&lt;/code&gt; function instead, which masks typed characters. This function is defined in a module under the same name, which is also available in the standard library:&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;getpass&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getpass&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &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;n&quot;&gt;getpass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Password: &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;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;s3cret&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;getpass&lt;/code&gt; module has another function for getting the user&amp;rsquo;s name from an environment variable:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;getpass&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getuser&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getuser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;jdoe&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python&amp;rsquo;s built-in functions for handling the standard input are quite limited. At the same time, there are plenty of third-party packages, which offer much more sophisticated tools.&lt;/p&gt;
&lt;h3 id=&quot;third-party&quot;&gt;Third-Party&lt;/h3&gt;
&lt;p&gt;There are external Python packages out there that allow for building complex graphical interfaces specifically to collect data from the user. Some of their features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Advanced formatting and styling&lt;/li&gt;
&lt;li&gt;Automated parsing, validation, and sanitization of user data&lt;/li&gt;
&lt;li&gt;A declarative style of defining layouts&lt;/li&gt;
&lt;li&gt;Interactive autocompletion&lt;/li&gt;
&lt;li&gt;Mouse support&lt;/li&gt;
&lt;li&gt;Predefined widgets such as checklists or menus&lt;/li&gt;
&lt;li&gt;Searchable history of typed commands&lt;/li&gt;
&lt;li&gt;Syntax highlighting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Demonstrating such tools is outside of the scope of this article, but you may want to try them out. I personally got to know about some of those through the &lt;a href=&quot;https://pythonbytes.fm/&quot;&gt;Python Bytes Podcast&lt;/a&gt;. Here they are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Mckinsey666/bullet&quot;&gt;&lt;code&gt;bullet&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pypi.org/project/cooked-input/&quot;&gt;&lt;code&gt;cooked-input&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pypi.org/project/prompt_toolkit/&quot;&gt;&lt;code&gt;prompt_toolkit&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kylebebak/questionnaire&quot;&gt;&lt;code&gt;questionnaire&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nonetheless, it&amp;rsquo;s worth mentioning a command line tool called &lt;code&gt;rlwrap&lt;/code&gt; that adds powerful line editing capabilities to your Python scripts for free. You don&amp;rsquo;t have to do anything for it to work!&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s assume you wrote a command-line interface that understands three instructions, including one for adding numbers:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Type &amp;quot;help&amp;quot;, &amp;quot;exit&amp;quot;, &amp;quot;add a [b [c ...]]&amp;quot;&amp;#39;&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;command&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;arguments&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;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;split&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;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&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;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&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;o&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;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&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;n&quot;&gt;lower&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;s1&quot;&gt;&amp;#39;help&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;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;This is help.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&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;n&quot;&gt;lower&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;s1&quot;&gt;&amp;#39;add&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;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;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arguments&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;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;Unknown command&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At first glance, it seems like a typical prompt when you run it:&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 calculator.py
&lt;span class=&quot;go&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;exit&amp;quot;, &amp;quot;add a [b [c ...]]&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;~ add 1 2 3 4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;~ aad 2 3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Unknown command&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;~ exit&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But as soon as you make a mistake and want to fix it, you&amp;rsquo;ll see that none of the function keys work as expected. Hitting the &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-arrow-left&quot;&gt;Left&lt;/kbd&gt;&lt;/span&gt; arrow, for example, results in this instead of moving the cursor back:&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 calculator.py
&lt;span class=&quot;go&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;exit&amp;quot;, &amp;quot;add a [b [c ...]]&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;~ aad^[[D&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, you can wrap the same script with the &lt;code&gt;rlwrap&lt;/code&gt; command. Not only will you get the arrow keys working, but you&amp;rsquo;ll also be able to search through the persistent history of your custom commands, use autocompletion, and edit the line with shortcuts:&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; rlwrap python calculator.py
&lt;span class=&quot;go&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;exit&amp;quot;, &amp;quot;add a [b [c ...]]&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(reverse-i-search)`a&amp;#39;: add 1 2 3 4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Isn&amp;rsquo;t that great?&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;re now armed with a body of knowledge about the &lt;code&gt;print()&lt;/code&gt; function in Python, as well as many surrounding topics. You have a deep understanding of what it is and how it works, involving all of its key elements. Numerous examples gave you insight into its evolution from Python 2.&lt;/p&gt;
&lt;p&gt;Apart from that, you learned how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid common mistakes with &lt;code&gt;print()&lt;/code&gt; in Python&lt;/li&gt;
&lt;li&gt;Deal with newlines, character encodings and buffering&lt;/li&gt;
&lt;li&gt;Write text to files&lt;/li&gt;
&lt;li&gt;Mock the &lt;code&gt;print()&lt;/code&gt; function in unit tests&lt;/li&gt;
&lt;li&gt;Build advanced user interfaces in the terminal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that you know all this, you can make interactive programs that communicate with users or produce data in popular file formats. You&amp;rsquo;re able to quickly diagnose problems in your code and protect yourself from them. Last but not least, you know how to implement the classic snake game.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re still thirsty for more information, have questions, or simply would like to share your thoughts, then feel free to reach out in the comments section below.&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>11 Beginner Tips for Learning Python</title>
      <id>https://realpython.com/courses/python-beginner-tips/</id>
      <link href="https://realpython.com/courses/python-beginner-tips/"/>
      <updated>2019-08-06T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll see several learning strategies and tips that will help you jumpstart your journey towards becoming a rockstar Python programmer!</summary>
      <content type="html">
        &lt;p&gt;We are so excited that you have decided to embark on the journey of learning Python! One of the most common questions we receive from our readers is “What’s the best way to learn Python?”&lt;/p&gt;
&lt;p&gt;The first step in learning any programming language is making sure that you understand how to learn. Learning how to learn is arguably the most critical skill involved in computer programming.&lt;/p&gt;
&lt;p&gt;Why is knowing how to learn so important? Languages evolve, libraries are created, and tools are upgraded. Knowing how to learn will be essential to keeping up with these changes and becoming a successful programmer.&lt;/p&gt;
&lt;p&gt;In this course, you&amp;rsquo;ll see several learning strategies that will help you jumpstart your journey towards becoming a rockstar Python programmer!&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>Dictionaries in Python</title>
      <id>https://realpython.com/courses/dictionaries-python/</id>
      <link href="https://realpython.com/courses/dictionaries-python/"/>
      <updated>2019-07-30T14:00:00+00:00</updated>
      <summary>In this course on Python dictionaries, you&#39;ll cover the basic characteristics of dictionaries and learn how to access and manage dictionary data. Once you&#39;ve finished this course, you&#39;ll have a good sense of when a dictionary is the appropriate data type to use and know how to use it.</summary>
      <content type="html">
        &lt;p&gt;Python provides a composite &lt;a href=&quot;https://realpython.com/python-data-types/&quot;&gt;data type&lt;/a&gt; called a &lt;strong&gt;dictionary&lt;/strong&gt;, which is similar to a &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;list&lt;/a&gt; in that it is a collection of objects.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here&amp;rsquo;s what you&amp;rsquo;ll learn in this course:&lt;/strong&gt; You&amp;rsquo;ll cover the basic characteristics of Python dictionaries and learn how to access and manage dictionary data.  Once you&amp;rsquo;ve finished this course, you&amp;rsquo;ll have a good sense of when a dictionary is the appropriate data type to use and know how to use it.&lt;/p&gt;
&lt;p&gt;Dictionaries and lists share the following characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Both are mutable.&lt;/li&gt;
&lt;li&gt;Both are dynamic.  They can grow and shrink as needed.&lt;/li&gt;
&lt;li&gt;Both can be nested. A list can contain another list. A dictionary can contain another dictionary.  A dictionary can also contain a list, and vice versa.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dictionaries differ from lists primarily in how elements are accessed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List elements are accessed by their position in the list, via indexing.&lt;/li&gt;
&lt;li&gt;Dictionary elements are accessed via keys.&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>Logging in Python</title>
      <id>https://realpython.com/courses/logging-python/</id>
      <link href="https://realpython.com/courses/logging-python/"/>
      <updated>2019-07-23T14:00:00+00:00</updated>
      <summary>In this video course, you&#39;ll learn why and how to get started with Python&#39;s powerful logging module to meet the needs of beginners and enterprise teams alike.</summary>
      <content type="html">
        &lt;p&gt;Logging is a very useful tool in a programmer’s toolbox. It can help you develop a better understanding of the flow of a program and discover scenarios that you might not even have thought of while developing.&lt;/p&gt;
&lt;p&gt;Logs provide developers with an extra set of eyes that are constantly looking at the flow that an application is going through. They can store information, like which user or IP accessed the application. If an error occurs, then they can provide more insights than a stack trace by telling you what the state of the program was before it arrived at the line of code where the error occurred.&lt;/p&gt;
&lt;p&gt;By logging useful data from the right places, you can not only debug errors easily but also use the data to analyze the performance of the application to plan for scaling or look at usage patterns to plan for marketing.&lt;/p&gt;
&lt;p&gt;Python provides a logging system as a part of its standard library, so you can quickly add logging to your application. In this course, you&amp;rsquo;ll learn why using this module is the best way to add logging to your application as well as how to get started quickly, and you will get an introduction to some of the advanced features available.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>How to Write Pythonic Loops</title>
      <id>https://realpython.com/courses/how-to-write-pythonic-loops/</id>
      <link href="https://realpython.com/courses/how-to-write-pythonic-loops/"/>
      <updated>2019-07-16T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll see how you can make your loops more Pythonic if you&#39;re coming to Python from a C-style language. You&#39;ll learn how you can get the most out of using range(), xrange(), and enumerate(). You&#39;ll also see how you can avoid having to keep track of loop indexes manually.</summary>
      <content type="html">
        &lt;p&gt;One of the easiest ways to spot a developer who has a background in C-style languages and only recently picked up Python is to look at how they loop through a list. In this course, you&amp;rsquo;ll learn how to take a C-style (Java, PHP, C, C++) loop and turn it into the sort of loop a Python developer would write.&lt;/p&gt;
&lt;p&gt;You can use these techniques to refactor your existing Python &lt;a href=&quot;https://realpython.com/python-for-loop/&quot;&gt;&lt;code&gt;for&lt;/code&gt; loops&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-while-loop/&quot;&gt;&lt;code&gt;while&lt;/code&gt; loops&lt;/a&gt; in order to make them easier to read and more maintainable. You&amp;rsquo;ll learn how to use Python&amp;rsquo;s &lt;a href=&quot;https://realpython.com/python-range/&quot;&gt;&lt;code&gt;range()&lt;/code&gt;, &lt;code&gt;xrange()&lt;/code&gt;&lt;/a&gt;, and &lt;code&gt;enumerate()&lt;/code&gt; built-ins to refactor your loops and how to avoid having to keep track of loop indexes manually.&lt;/p&gt;
&lt;p&gt;The main takeaways in this tutorial are that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Writing C-style loops in Python is considered not &lt;a href=&quot;https://realpython.com/learning-paths/writing-pythonic-code/&quot;&gt;Pythonic&lt;/a&gt;. Avoid managing loop indexes and stop conditions manually if possible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Python’s &lt;code&gt;for&lt;/code&gt; loops are really “for each” loops that can iterate over items from a container or sequence directly.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&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>Reading and Writing Files in Python</title>
      <id>https://realpython.com/courses/reading-and-writing-files-python/</id>
      <link href="https://realpython.com/courses/reading-and-writing-files-python/"/>
      <updated>2019-07-09T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll learn about reading and writing files in Python. You&#39;ll cover everything from what a file is made up of to which libraries can help you along that way. You&#39;ll also take a look at some basic scenarios of file usage as well as some advanced techniques.</summary>
      <content type="html">
        &lt;p&gt;In this course, you&amp;rsquo;ll learn about reading and writing files in Python. You&amp;rsquo;ll cover everything from what a file is made up of to which libraries can help you along that way. You&amp;rsquo;ll also take a look at some basic scenarios of file usage as well as some advanced techniques.&lt;/p&gt;
&lt;p&gt;One of the most common tasks that you can do with Python is reading and writing files. Whether it’s writing to a simple text file, reading a complicated server log, or even analyzing raw byte data, all of these situations require reading or writing a file.&lt;/p&gt;
&lt;p&gt;By the end of this course, you’ll know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What makes up a file and why that’s important in Python&lt;/li&gt;
&lt;li&gt;The basics of reading and writing files in Python&lt;/li&gt;
&lt;li&gt;Some basic scenarios of reading and writing files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This tutorial is mainly for beginner to intermediate Pythonistas, but there are some tips in here that more advanced programmers may appreciate as well.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  

</feed>
