{"id":514,"date":"2016-04-18T09:00:47","date_gmt":"2016-04-18T17:00:47","guid":{"rendered":"http:\/\/blogs.msdn.microsoft.com\/pythonengineering\/?p=514"},"modified":"2019-02-17T15:27:09","modified_gmt":"2019-02-17T22:27:09","slug":"idiomatic-python-boolean-expressions","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/python\/idiomatic-python-boolean-expressions\/","title":{"rendered":"Idiomatic Python: boolean expressions"},"content":{"rendered":"<p>You might think that boolean expressions &#8212; most frequently used as conditional guards which are the the bit of code that tests whether an <code>if<\/code> or <code>while<\/code> statement should execute &#8212; are a fairly straight-forward concept and that there isn&#8217;t really anything subtle to them at all. And while the general concept is simple, there are some idiomatic practices to follow when writing them.<\/p>\n<p>To start off, we should make sure everyone understands what makes something considered true or false (sometimes referred to as being &#8220;truthy&#8221; or not). The official <a href=\"https:\/\/docs.python.org\/3\/reference\/expressions.html#booleans\">definition of what is true or false<\/a> in Python 3 is:<\/p>\n<blockquote><p><code>False<\/code>, <code>None<\/code>, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as being true. User-defined objects can customize their truth value by providing a <code>__bool__()<\/code> method.<\/p><\/blockquote>\n<p>A bit of Python history: During the discussion of <a href=\"https:\/\/docs.python.org\/3\/whatsnew\/2.3.html#pep-285-a-boolean-type\">adding the boolean type in Python 2.3<\/a>, some people didn&#8217;t like that the definition of what was considered false went from &#8220;anything that represents emptiness&#8221;, to &#8220;anything that represents emptiness <strong>and<\/strong> <code>False<\/code>&#8221; which some viewed as a loss of simplicity. On the other side people argued that <code>False<\/code> helped make code clearer. In the end the side arguing that the concept of <code>False<\/code> was larger and thus the side for clearer code won. You might also have noticed that booleans are not <em>that<\/em> old in Python, which is why booleans can (mostly) be treated as integers due to backwards-compatibility with code that simply used <code>1<\/code> and <code>0<\/code> to represent <code>True<\/code> and <code>False<\/code>, respectively.<\/p>\n<p>The first piece of advice is to not overdo the use of <code>is<\/code> comparisons. The <code>is<\/code> is for <a href=\"https:\/\/docs.python.org\/3\/reference\/expressions.html#is-not\">identity comparisons<\/a> which means it evaluates to <code>True<\/code> only if both objects involved in the expression are literally the same object (this has nothing to do with value). Unfortunately people can easily end up conflating an identity comparison with a value comparison. For instance, some people accidentally discover that some implementations of Python cache certain values for performance, leading to expressions like:<\/p>\n<pre>40 + 2 is 42  # True in CPython, not necessarily in other VMs.<\/pre>\n<p>being true. But this caching of numbers isn&#8217;t part of the language definition of Python, making it just a quirky side-effect of an implementation detail. This is a problem then if you either change Python implementations or happen to think that using <code>is<\/code> with numbers works with any number, which isn&#8217;t true if you try something like:<\/p>\n<pre>2**32 is 2**32 # False.<\/pre>\n<p>which evaluates to <code>False<\/code>. In other words, only use <code>is<\/code> if you really, <strong>really<\/strong> want to test for identity and not value.<\/p>\n<p>Another place where we have seen <code>is<\/code> used in a non-idiomatic fashion is directly testing for <code>True<\/code> or <code>False<\/code>, e.g.:<\/p>\n<pre>something() is False  # Too restrictive.<\/pre>\n<p>This is technically not wrong like with the previous example because <code>False<\/code> is a singleton &#8212; just like <code>None<\/code> and <code>True<\/code> &#8212; which means there is only one instance of <code>False<\/code> to actually compare against. Where this goes astray is it is unnecessarily restrictive. Thanks to Python being a huge proponent of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Duck_typing\">duck typing<\/a>, tying down any API specifically to only <code>True<\/code> or <code>False<\/code> is frowned upon as it locks an API to a specific type. If for some reason the API changed to return values of a different type but has the same boolean interpretation then this code would suddenly break. Instead of directly checking for <code>False<\/code>, the code should have simply checked for false value:<\/p>\n<pre>not something()  # Just right.<\/pre>\n<p>And this extends to other types as well, so don&#8217;t do <code>spam == []<\/code> if you care if something is empty, simply do <code>not spam<\/code> in case the API that gave you the value for <code>spam<\/code> suddenly starts returning tuples instead of lists.<\/p>\n<p>About the only time you might legitimately find the need to use <code>is<\/code> in day-to-day code is with <code>None<\/code>. Sometimes you might come across an API where <code>None<\/code> has special meaning, in which case you should use <code>is None<\/code> to check for that specific value. For example, modules in Python have a <a href=\"https:\/\/docs.python.org\/3\/reference\/import.html#__package__\"><code>__package__<\/code> attribute<\/a> which stores a string representing what package the module belongs to. The trick is that top-level modules &#8212; i.e., modules that are not contained in a package &#8212; have <code>__package__<\/code> set to the empty string which is false but is a valid value, but there is a need to have a value represent not knowing what <code>__package__<\/code> should be set to. In that instance, <code>None<\/code> is used to represent &#8220;I don&#8217;t know&#8221;. This allows the <a href=\"https:\/\/github.com\/python\/cpython\/blob\/d0ffca8d6aa055300f7361e4bea2d4def0fca571\/Lib\/importlib\/_bootstrap.py#L1031\">code that calculates what package a module belongs to<\/a> to use:<\/p>\n<pre>package is None  # OK when you need an \"I don't know\" value.<\/pre>\n<p>to detect if the package name isn&#8217;t known (<code>not package<\/code> would incorrectly think that <code>''<\/code> represented that as well). Do make sure to not overuse this kind of use of <code>None<\/code>, though, as a false value tends to meet the need of representing &#8220;I don&#8217;t know&#8221;.<\/p>\n<p>Another bit of advice is to think twice before defining <code>__bool__()<\/code> on our own classes. While you should definitely define the method on classes representing containers (to help with that &#8220;empty if false&#8221; concept), in all cases you should\u00a0stop and think about whether it truly makes sense to define the method. While it may be tempting to use <code>__bool__()<\/code> to represent some sort of state of an object, the ramifications can be surprisingly far-reaching as it means suddenly people have to start explicitly checking for some special value like <code>None<\/code>\u00a0which represents whether an API returned an actual value or not instead of simply relying on all object defaulting to being true. As an example of how defining <code>__bool__()<\/code> can be surprising, see the <a href=\"https:\/\/bugs.python.org\/issue13936\">Python issue<\/a> where there was a multi-year discussion over how defining <code>datetime.time()<\/code> to be false at midnight but true for all other values was a mistake and how best to fix it (in the end the implementation of <code>__bool__()<\/code> was <a href=\"https:\/\/docs.python.org\/3\/whatsnew\/3.5.html#changes-in-the-python-api\">removed in Python 3.5<\/a>).<\/p>\n<p>If you find yourself needing to provide a specific default value when faced with a possible false value, using <code>or<\/code> can be helpful. Both <code>and<\/code> and <code>or<\/code> don&#8217;t return a specific boolean value but the first value that forces a known true value. In the case of <code>or<\/code> this means either the first value if it is true or else the last value no matter what. This means that if you had something like:<\/p>\n<pre># Use the value from something() if it is true, else default to None.\nspam = something() or None<\/pre>\n<p>then <code>spam<\/code> would gain the value from <code>something()<\/code> if it was true, else it would be set to <code>None<\/code>. And because both <code>and<\/code> and <code>or<\/code> short-circuit, you can combine this with some object instantiation and know that it won&#8217;t occur unless necessary;<\/p>\n<pre># Only execute AnotherThing() if something() returns a false value.\nspam = something() or AnotherThing()<\/pre>\n<p>won&#8217;t actually execute <code>AnotherThing()<\/code> unless <code>something()<\/code> returns a false value.<\/p>\n<p>And finally, make sure to use <a href=\"https:\/\/docs.python.org\/3\/library\/functions.html#any\"><code>any()<\/code><\/a> and <a href=\"https:\/\/docs.python.org\/3\/library\/functions.html#all\"><code>all()<\/code><\/a> when possible. These built-in functions are very convenient when they are needed and when combined with generator expressions they are rather powerful.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You might think that boolean expressions &#8212; most frequently used as conditional guards which are the the bit of code that tests whether an if or while statement should execute &#8212; are a fairly straight-forward concept and that there isn&#8217;t really anything subtle to them at all. And while the general concept is simple, there [&hellip;]<\/p>\n","protected":false},"author":386,"featured_media":10119,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[9,13],"class_list":["post-514","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python","tag-code-style","tag-idioms"],"acf":[],"blog_post_summary":"<p>You might think that boolean expressions &#8212; most frequently used as conditional guards which are the the bit of code that tests whether an if or while statement should execute &#8212; are a fairly straight-forward concept and that there isn&#8217;t really anything subtle to them at all. And while the general concept is simple, there [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts\/514","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/users\/386"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/comments?post=514"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts\/514\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/media\/10119"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/media?parent=514"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/categories?post=514"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/tags?post=514"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}