<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.0">Jekyll</generator><link href="https://sethdandridge.com/blog/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sethdandridge.com/blog/" rel="alternate" type="text/html" /><updated>2021-02-16T16:51:37+00:00</updated><id>https://sethdandridge.com/blog/feed.xml</id><title type="html">Seth Dandridge</title><subtitle>Writings on Python, web development, and other pursuits.</subtitle><entry><title type="html">Evaluating Boolean Expressions to a Variable</title><link href="https://sethdandridge.com/blog/evaluating-boolean-expressions-to-a-variable" rel="alternate" type="text/html" title="Evaluating Boolean Expressions to a Variable" /><published>2021-02-16T16:30:00+00:00</published><updated>2021-02-16T16:30:00+00:00</updated><id>https://sethdandridge.com/blog/evaluating-boolean-expressions-to-a-variable</id><content type="html" xml:base="https://sethdandridge.com/blog/evaluating-boolean-expressions-to-a-variable">&lt;p&gt;Hot off Python inventor Guido van Rossum’s &lt;a href=&quot;https://twitter.com/gvanrossum/status/1359325911993098241&quot;&gt;stunning endorsement of last week’s deep dive into function attributes&lt;/a&gt;, here’s a little tidbit from an ongoing series of Python minutiae I’m calling &lt;a href=&quot;/blog/tag/baby-snakes&quot;&gt;Baby Snakes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(Before continuing, I should disclaim that this is my personal opinion on a matter of style. Coding is an art—&lt;a href=&quot;https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition&quot;&gt;even bad code can be art&lt;/a&gt;—and one could easily raise practical and aesthetic arguments against my opinions on code style.)&lt;/p&gt;
&lt;h1 id=&quot;using-boolean-expressions&quot;&gt;Using Boolean Expressions&lt;/h1&gt;
&lt;p&gt;I occasionally see inexperienced (and not-so-inexperienced) developers use this pattern:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#&amp;gt; Don't do this:
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;some_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is_some_value_greater&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is_some_value_greater&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What’s wrong with it? Although syntactically and logically correct, it suggests a novice understanding of the nature of boolean expressions.&lt;/p&gt;

&lt;p&gt;An expression is a piece of code that evaluates to a value. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 + 1&lt;/code&gt; is an expression that evaluates to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;. Function calls are expressions since they always evaluate to a value (even if that value is an implicitly returned &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;). A boolean expression is an expression that evaluates to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;. In the above snippet, the code between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; is a boolean expression.&lt;/p&gt;
&lt;h1 id=&quot;evaluating-expressions-to-a-variable&quot;&gt;Evaluating Expressions to a Variable&lt;/h1&gt;
&lt;p&gt;Everyone feels comfortable assigning the result of a mathematical operation or function call to a variable. As noted above, mathematical operations and function calls are both expressions. Why should boolean expressions be treated any differently?&lt;/p&gt;

&lt;p&gt;In place of a multi-line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if/else&lt;/code&gt; statement, assign the result of the boolean expression directly to the variable:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;is_some_value_greater&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;some_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_value&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This pattern works with any combination of logical, comparison, identity, and membership operators:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;is_equal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;some_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_value&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;is_dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fido&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dog&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;is_clean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BadThing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thing&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;list_of_things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;boolean-ternary-expressions&quot;&gt;Boolean Ternary Expressions&lt;/h1&gt;
&lt;p&gt;An even less stylish pattern than multi-line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if/else&lt;/code&gt; statements is misuse of conditional expressions, like this funny one-liner:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#&amp;gt; Don't do this:
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_some_value_greater&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;some_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other_value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Conditional expressions evaluate to either the leftmost or rightmost value depending on whether the expression between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt; evaluates to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;. It’s redundant to wrap a boolean expression in a conditional expression if that conditional expression is merely returning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;;  you can assign the result of the boolean expression directly to a variable and avoid the conditional expression syntax entirely.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;br /&gt; 
This is the third article in my &lt;a href=&quot;/blog/tag/baby-snakes&quot;&gt;Baby Snakes&lt;/a&gt; series, a collection of Python arcana aimed at intermediate and advanced Python developers. For future updates, &lt;a href=&quot;https://twitter.com/sethdandridge&quot;&gt;follow me on Twitter&lt;/a&gt;!&lt;/p&gt;</content><author><name></name></author><category term="Python" /><category term="baby snakes" /><summary type="html">Hot off Python inventor Guido van Rossum’s stunning endorsement of last week’s deep dive into function attributes, here’s a little tidbit from an ongoing series of Python minutiae I’m calling Baby Snakes.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://sethdandridge.com/blog/assets/img/2021-02-16-assigning-the-rules-of-a-boolean-expression-to-a-variable-social.png" /><media:content medium="image" url="https://sethdandridge.com/blog/assets/img/2021-02-16-assigning-the-rules-of-a-boolean-expression-to-a-variable-social.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Assigning Attributes to Python Functions</title><link href="https://sethdandridge.com/blog/assigning-attributes-to-python-functions" rel="alternate" type="text/html" title="Assigning Attributes to Python Functions" /><published>2021-02-07T18:59:00+00:00</published><updated>2021-02-07T18:59:00+00:00</updated><id>https://sethdandridge.com/blog/assigning-attributes-to-python-functions</id><content type="html" xml:base="https://sethdandridge.com/blog/assigning-attributes-to-python-functions">&lt;p&gt;I was surprised to learn that functions and methods can be assigned attributes, similarly to how one can assign attributes to classes, class instances, and most other objects:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_thing&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;do_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;whatever&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hi&quot;&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;n&quot;&gt;do_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;whatever&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; hi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;wat&quot;&gt;Wat?&lt;/h1&gt;

&lt;p&gt;For what reason is this even possible?&lt;/p&gt;

&lt;p&gt;You might be thinking:&lt;/p&gt;

&lt;p&gt;“Of course this works. Functions are objects. Everything is an object. And therefore it makes sense that functions have assignable attributes. Classes are objects. Classes have assignable attributes. Functions are also objects. Therefore functions must also have assignable attributes.”&lt;/p&gt;

&lt;p&gt;Well, just because something is an object doesn’t mean it’s an attribute assignment free-for-all. In fact, Python explicitly forbids attribute assignment in a couple common cases.&lt;/p&gt;

&lt;p&gt;For example you can’t assign attributes to built-in functions:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;n&quot;&gt;some_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; AttributeError: 'builtin_function_or_method' object has no attribute 'some_data'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And you can’t assign attributes to built-in types:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;stringy string&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;some_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; AttributeError: 'str' object has no attribute 'some_data'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And yes, both are objects:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; True
&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;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; True&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Surprisingly though, Python allows attribute assignment to (non-built-in) functions and methods. And you can put anything you want in there! Check it out:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_thing&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;n&quot;&gt;do_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sneaky_func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;do_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sneaky_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;print('O_o')&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; O_o&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;why&quot;&gt;Why&lt;/h1&gt;

&lt;p&gt;This has not always been the case. Functions did not initially support attribute assignment. But despite not supporting attribute assignment, functions were never entirely attribute-less. In even the earlier days of Python, functions had a number of attributes, including a few that were writeable—namely &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__doc__&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you’ve ever documented your code, you’re probably familiar with &lt;a href=&quot;https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html&quot;&gt;docstrings&lt;/a&gt;. Docstrings are syntactic sugar that enable one to write documentation for modules, classes, methods and functions by putting an inline string literal at the top of the object’s definition:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Here's some documentation&quot;&quot;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&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;n&quot;&gt;do_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; Help on function do_thing in module __main__:
#&amp;gt; do_thing()
#&amp;gt;    Here's some documentation&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The docstring of a function is stored in its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__doc__&lt;/code&gt; attribute:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Here's some documentation&quot;&quot;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&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;n&quot;&gt;do_thing&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;c1&quot;&gt;#&amp;gt; Here's some documentation&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So what do docstrings have to do with function attributes?&lt;/p&gt;

&lt;p&gt;In the earlier days of Python, engineers began hijacking docstrings for untoward purposes—not using the docstring for documentation, but instead for storing other programmatically accessible information about the function.&lt;/p&gt;

&lt;p&gt;John Aycock, for example, wrote a &lt;a href=&quot;https://web.archive.org/web/19991103084100/http://www.foretec.com/python/workshops/1998-11/proceedings/papers/aycock-little/aycock-little.html&quot;&gt;clever parsing system&lt;/a&gt; that decided whether to apply a method to a target string by evaluating whether that target string matched a regular expression contained in the method’s docstring.&lt;/p&gt;

&lt;p&gt;In response to docstring exploitation, Barry Warsaw proposed &lt;a href=&quot;https://www.python.org/dev/peps/pep-0232/#background&quot;&gt;PEP 232&lt;/a&gt;, an extension to the Python language adding support for method/function attributes. It was approved and implemented in Python 2.1+.&lt;/p&gt;

&lt;h1 id=&quot;when-is-it-appropriate-to-use-function-attributes&quot;&gt;When Is It Appropriate To Use Function Attributes?&lt;/h1&gt;

&lt;p&gt;In my opinion: rarely.&lt;/p&gt;

&lt;p&gt;Many experienced Pythonistas aren’t aware that it is even possible to assign function attributes. If you’re doing work-a-day software development, lack of familiarity in the community is usually a red flag for a language feature.&lt;/p&gt;

&lt;p&gt;That being said, there are valid reasons one might store metadata on a function.&lt;/p&gt;

&lt;p&gt;Function attributes are useful if you are passing functions around and need to a way to graft information onto those functions to use later. Perhaps you’re writing a higher order function—a function that takes a function as an argument. You might want your higher order function to treat the lower order function differently depending on the value stored in an attribute of the function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dog_feeder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;food_type&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;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'feeding &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;food_type&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; to the dog'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;dog_feeder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;species&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'dog'&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cat_feeder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;food_type&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;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'feeding &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;food_type&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; to the cat'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cat_feeder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;species&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'cat'&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;feed_pet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feed_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Higher order function that takes a feed function as argument
&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feed_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;species&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'dog'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;feed_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'dog food'&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;feed_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;species&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'cat'&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;n&quot;&gt;feed_pet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dog_feeder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; feeding dog food to the dog
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;feed_pet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cat_feeder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I should note that in Python 3.4+, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;functools.singledispatch&lt;/code&gt; decorator better serves the above use case. I’ll talk about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;singledispatch&lt;/code&gt; in a future post. But my point stands: when doing higher-order programming, it can be useful for functions to carry around data about themselves.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0232/#background&quot;&gt;PEP 232&lt;/a&gt; and Paul Prescod’s &lt;a href=&quot;https://mail.python.org/pipermail/python-dev/2000-April/003364.html&quot;&gt;message to the python-dev mailing list&lt;/a&gt; describe a few other use cases.&lt;/p&gt;

&lt;p&gt;For example, one might want to define different docstring formats in order to accommodate different IDEs or documentation methodologies.&lt;/p&gt;

&lt;p&gt;In a similar vein as John Aycock’s parser: if you’re writing a class for traversing a data structure, and you want to associate particular node types with certain methods, the list of node types that a method supports can be stored as an attribute of that method.&lt;/p&gt;

&lt;h1 id=&quot;when-is-it-not-appropriate-to-use-function-attributes&quot;&gt;When Is It Not Appropriate To Use Function Attributes?&lt;/h1&gt;

&lt;p&gt;If you need a quick-and-dirty data store and believe dot notation is prettier than dict[key]:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;settings&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;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'0.0.0.0'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Seriously, don’t do this. If the above code landed on my desk for review, I’d give the engineer a sincere pat on the back for being clever, then politely request they be sent to the gulag for their crimes.&lt;/p&gt;

&lt;p&gt;If you need a store of data, use a dictionary, class, or even a module. Anything but a function.&lt;/p&gt;

&lt;p&gt;Another deeply inappropriate reason for leveraging function attributes is that you are dissatisfied with off-the-shelf class behavior and want to create functions that sort of behave like classes. You can accomplish that with function attributes and a funky bit of recursion:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Dog&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;bark&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;s&quot;&gt;&quot;bark bark&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bark&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dog&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;fido&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fido&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; bark bark&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Please don’t do this either.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;I hope you enjoyed this deep-ish dive into Python function attributes. This is one article in a series on Python arcana I’ll be publishing over the course of the next few months. Check back soon for more!&lt;/p&gt;</content><author><name></name></author><category term="Python" /><category term="verboten magick" /><summary type="html">I was surprised to learn that functions and methods can be assigned attributes, similarly to how one can assign attributes to classes, class instances, and most other objects:</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://sethdandridge.com/blog/assets/img/2021-02-07-assigning-attributes-to-python-functions.jpg" /><media:content medium="image" url="https://sethdandridge.com/blog/assets/img/2021-02-07-assigning-attributes-to-python-functions.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Defining a Custom Class Constructor in Python</title><link href="https://sethdandridge.com/blog/defining-a-custom-class-constructor-in-python" rel="alternate" type="text/html" title="Defining a Custom Class Constructor in Python" /><published>2021-02-01T00:00:00+00:00</published><updated>2021-02-01T00:00:00+00:00</updated><id>https://sethdandridge.com/blog/defining-a-custom-class-constructor-in-python</id><content type="html" xml:base="https://sethdandridge.com/blog/defining-a-custom-class-constructor-in-python">&lt;p&gt;Python gives you tremendous visibility into its internal workings. The degree to which you can pop open the hood and modify what’s happening at runtime is powerful and terrifying. The author of the venerable Flask web framework Armin Ronacher gave a fantastic talk on this topic called &lt;a href=&quot;https://www.youtube.com/watch?v=qCGofLIzX6g&quot;&gt;How Python was Shaped by Leaky Internals&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One way to take advantage of these leaky internals is by overwriting the built-in class constructor. Whenever you define a class, the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt; is called behind the scenes. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt; is passed the class code (which is actually, suprisingly, a function) and the class name as arguments. The result of executing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt; is your class being created in the appropriate namespace. I’m &lt;a href=&quot;https://www.pythoninsight.com/2019/03/what-happens-when-a-class-is-created/&quot;&gt;simplifying&lt;/a&gt;, but bear with me.&lt;/p&gt;

&lt;h1 id=&quot;investigating-__build_class__&quot;&gt;Investigating __build_class__&lt;/h1&gt;

&lt;p&gt;To see this in action, let’s define a simple class called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt; and observe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt; do its job.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&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;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'bark bark'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; bark bark&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now let’s define a custom build class function to see a bit of what’s happening under the hood.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;custom_build_class&lt;/span&gt;&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;__builtins__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__build_class__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_build_class&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&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;#&amp;gt; (&amp;lt;function Dog at 0x10f6ff6a8&amp;gt;, 'Dog')&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can see the two arguments that are passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt; are the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt; function (the code of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt; class) and the name of the class, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'Dog'&lt;/code&gt;. Because we don’t ever call the “real” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt;, the class is never defined in the namespace. Curiously, however, accessing the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt; doesn’t throw &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NameError&lt;/code&gt;. Instead, it’s just&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;n&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; None&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Not sure why this is—evidently there’s something outside of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt; that’s modifying the namespace. Worth further investigation.&lt;/p&gt;

&lt;h1 id=&quot;redefining-__build_class__&quot;&gt;Redefining __build_class__&lt;/h1&gt;
&lt;p&gt;Now let’s redefine the built-in class constructor so that no matter what class you define, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt; function assigns the code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt; to that class name instead of the code of the class you’re defining.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&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;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'woof woof'&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;custom_build_class&lt;/span&gt;&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dog&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;__builtins__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__build_class__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_build_class&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Cat&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;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'meow meow'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; bark bark
&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;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;gt; &amp;lt;class '__main__.Dog'&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Chaos reigns!&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Aside from impressing your friends and coworkers with verboten Python magic, why would you ever want to do any of this? I actually can’t think of a legitimate reason. Perhaps you need a hook that registers every class upon its creation? However, this case would probably be better served with a metaclass. If you can think of a legitimate real-world scenario for overriding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__build_class__&lt;/code&gt;, let me know.&lt;/p&gt;

&lt;p&gt;This is the second in a series of blog entries I’m calling “baby snakes”, bits of Python arcana aimed at intermediate and advanced Python developers. For a similar exercise in Python’s built-in abuse, see &lt;a href=&quot;/blog/redefining-pythons-print-function&quot;&gt;Redefining Python’s Print() Function&lt;/a&gt; and check back soon for even more!&lt;/p&gt;</content><author><name></name></author><category term="Python" /><category term="baby snakes" /><category term="verboten magick" /><summary type="html">Python gives you tremendous visibility into its internal workings. The degree to which you can pop open the hood and modify what’s happening at runtime is powerful and terrifying. The author of the venerable Flask web framework Armin Ronacher gave a fantastic talk on this topic called How Python was Shaped by Leaky Internals.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://sethdandridge.com/blog/assets/img/2021-02-01-defining-a-custom-class-constructor-in-python-social.png" /><media:content medium="image" url="https://sethdandridge.com/blog/assets/img/2021-02-01-defining-a-custom-class-constructor-in-python-social.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Redefining Python’s Print() Function</title><link href="https://sethdandridge.com/blog/redefining-pythons-print-function" rel="alternate" type="text/html" title="Redefining Python’s Print() Function" /><published>2021-01-25T14:27:00+00:00</published><updated>2021-01-25T14:27:00+00:00</updated><id>https://sethdandridge.com/blog/redefining-pythons-print-function</id><content type="html" xml:base="https://sethdandridge.com/blog/redefining-pythons-print-function">&lt;p&gt;Every novice Pythonista is familiar with the trusty built-in function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt;. Its job is simple: output the string representation of an object or expression.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;s&quot;&gt;'the answer is'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;'the answer is 3'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;But let’s say you want to change the behavior of print. Instead of sending its output to the terminal, let’s send that output to a file on the disk. We can accomplish this by redefining the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print&lt;/code&gt; variable.&lt;/p&gt;

&lt;h1 id=&quot;printing-to-a-file&quot;&gt;Printing to a File&lt;/h1&gt;

&lt;p&gt;The full function signature of print is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;n&quot;&gt;objects&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;s&quot;&gt;' '&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;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&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;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note the third keyword argument, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file&lt;/code&gt;. The default value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sys.stdout&lt;/code&gt;, which represents the terminal output buffer. The only real requirement for the object passed as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file&lt;/code&gt; is that it has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.write()&lt;/code&gt; method. You know what has a write method? File handlers.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;s&quot;&gt;'log.txt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'a+'&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;c1&quot;&gt;# f is a file handler
&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;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'the answer is'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s redefine the print variable to instead be a wrapper function around the vanilla built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt;. The wrapped &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt; needs to be referenced through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;builtins&lt;/code&gt; module so that we don’t define a recursive function.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;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;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;s&quot;&gt;'log.txt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'a+'&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builtins&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;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&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;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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'the answer is'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, when we call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt;, no output is displayed in the terminal. However, if we read the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log.txt&lt;/code&gt;, we can see that our redefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt; has written to the file.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;log.txt
the answer is 3&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;print-as-a-buffer-object&quot;&gt;Print as a Buffer Object&lt;/h1&gt;

&lt;p&gt;Let’s make it weird. We can actually redefine &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt; to be a buffer object that stores all the strings that are passed to it for printing. Instead of a function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print&lt;/code&gt; will be an instance of a class that inherits &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.StringIO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringIO&lt;/code&gt; is a in-memory text buffer that works similarly to a file handler. In fact, file handlers and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringIO&lt;/code&gt; both implement the abstract base class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IOBase&lt;/code&gt;, which means they have many of the same methods defined.&lt;/p&gt;

&lt;p&gt;Here’s a simple example of how to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringIO&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;nb&quot;&gt;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;p&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;nb&quot;&gt;buffer&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;s&quot;&gt;'here is some input'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&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;s&quot;&gt;'here is some input'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s define a new subclass of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringIO&lt;/code&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PrintWrapper&lt;/code&gt;. We’re also going to define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__call__&lt;/code&gt; magic method on this new class. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__call__&lt;/code&gt; allows you to define how an instance of a class behaves when it is called like a function.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&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;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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PrintWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__call__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;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;c1&quot;&gt;# Pass the object instance (self) as the file
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builtins&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;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;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;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrintWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# print is now the printer AND a buffer
&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;s&quot;&gt;'this was added to buffer'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# triggers print.__call__()
&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;s&quot;&gt;'this was also added to the buffer'&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;n&quot;&gt;getvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;'this was added to buffer&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;this was also added to buffer&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Strings that you have printed are seperated by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n&lt;/code&gt; when you call print.getvalue(), but you can define a different seperator by passing it as a string to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end=&lt;/code&gt; keyword argument of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;builtins.print()&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Why would you ever want to do any of this? Let’s say you are building a web-based programming environment like &lt;a href=&quot;https://coderpad.io/&quot;&gt;CoderPad&lt;/a&gt;. When a user calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt;, you wouldn’t want the Python interpreter running on the server to send the printed statement to stdout. You want it outputted to a handler that transmits it to the user’s browser over the Internet. There are probably other ways to accomplish this, but redefining &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt; behind the scenes is one possibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; As Reddit user Dasher38 &lt;a href=&quot;https://www.reddit.com/r/Python/comments/l4u18p/redefining_pythons_print_function/gkt3vlc/&quot;&gt;points out&lt;/a&gt;, there’s a context manager in the standard library &lt;a href=&quot;https://docs.python.org/3/library/contextlib.html#contextlib.redirect_stdout&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contextlib.redirect_stdout&lt;/code&gt;&lt;/a&gt; that is better suited for redirecting the output of a web-based programming environment backend. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redirect_stdout&lt;/code&gt; redirects everything sent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sys.stdout&lt;/code&gt; (including printed statements) to a specified file-like object. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;br /&gt; 
This is the first of a series of blog entries I’m calling “baby snakes”, bits of Python arcana aimed at intermediate and advanced Python developers. Check back soon for more!&lt;/p&gt;</content><author><name></name></author><category term="Python" /><category term="baby snakes" /><category term="verboten magick" /><summary type="html">Every novice Pythonista is familiar with the trusty built-in function print(). Its job is simple: output the string representation of an object or expression.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://sethdandridge.com/blog/assets/img/2021-01-25-redefining-pythons-print-function-social.jpg" /><media:content medium="image" url="https://sethdandridge.com/blog/assets/img/2021-01-25-redefining-pythons-print-function-social.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Hello World!</title><link href="https://sethdandridge.com/blog/hello-world" rel="alternate" type="text/html" title="Hello World!" /><published>2021-01-20T18:06:17+00:00</published><updated>2021-01-20T18:06:17+00:00</updated><id>https://sethdandridge.com/blog/hello-world</id><content type="html" xml:base="https://sethdandridge.com/blog/hello-world">&lt;p&gt;Welcome to my new blog! Over the past few years I’ve collected a number of writings to share. These mostly focus on the Python programming language and other software engineering topics, but occasionally there will be a few random side-obsessions thrown in to keep things spicy.&lt;/p&gt;

&lt;p&gt;For the time being, this site is powered by the static site generator &lt;a href=&quot;https://github.com/jekyll/jekyll&quot;&gt;Jekyll&lt;/a&gt; and a lightly modified version of its default theme, Minima.&lt;/p&gt;

&lt;p&gt;A few other options were considered before I settled on Jekyll:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Write my own static site generator in Python&lt;/li&gt;
  &lt;li&gt;Write my own dynamic content management system from scratch using Flask&lt;/li&gt;
  &lt;li&gt;Use an existing Python-based static site generator like Pelican&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, I ultimately decided on Jekyll. Even though it’s written in Ruby, with which I have next to nil experience, I liked the default theme and it was a much faster route to getting words on the screen than something written from scratch.&lt;/p&gt;

&lt;p&gt;Anyway, happy reading and I hope you enjoy my musings.&lt;/p&gt;</content><author><name></name></author><category term="Misc" /><category term="web development" /><category term="personal infrastructure" /><summary type="html">Welcome to my new blog! Over the past few years I’ve collected a number of writings to share. These mostly focus on the Python programming language and other software engineering topics, but occasionally there will be a few random side-obsessions thrown in to keep things spicy.</summary></entry></feed>