Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tut] How to Check If a Python List is Empty?

#1
How to Check If a Python List is Empty?

<div><p>Believe it or not—how you answer this question in your day-to-day code reveals your true Python skill level to every master coder who reads your code. </p>
<figure class="wp-block-image size-large is-resized"><img src="https://blog.finxter.com/wp-content/uploads/2020/05/truth_value_testing-1024x576.jpg" alt="How to Check if List is Empty Python" class="wp-image-9092" width="768" height="432" srcset="https://blog.finxter.com/wp-content/uploads/2020/05/truth_value_testing-scaled.jpg 1024w, https://blog.finxter.com/wp-content/uplo...00x169.jpg 300w, https://blog.finxter.com/wp-content/uplo...68x432.jpg 768w" sizes="(max-width: 768px) 100vw, 768px" /></figure>
<p>Beginner coders check if a list <code>a</code> is empty using crude statements like <code>len(a)==0</code> or <code>a==[]</code>. While those solve the problem—they check if a list is empty—they are not what a master coder would do. Instead, the most Pythonic way to check if a list (or any other iterable for that matter) is empty is the expression <code>not a</code>. </p>
<p>You may call it <a rel="noreferrer noopener" href="https://docs.python.org/3/library/stdtypes.html#truth-value-testing" target="_blank"><em>implicit Booleanness</em></a> (or, more formal, <strong><em>type flexibility</em></strong>): every object in Python can be implicityl converted into a truth value. </p>
<p>Here’s an example in our interactive Python shell—try it yourself! </p>
<p> <iframe src="https://trinket.io/embed/python/c0afe4f107" marginwidth="0" marginheight="0" allowfullscreen="" width="100%" height="400" frameborder="0"></iframe> </p>
<p><em><strong>Exercise</strong>: What’s the output of the code if you add one element to the list <code>a</code>?</em></p>
<h2>Truth Value Testing and Type Flexibility</h2>
<p>Python implicitly associates any object with a Boolean value. Here are some examples:</p>
<ul>
<li>The integers 1, 2, and 3 are associated to the Boolean <code>True</code>.</li>
<li>The integer 0 is associated to the Boolean <code>False</code>.</li>
<li>The strings <code>'hello'</code>, <code>'42'</code>, and <code>'0'</code> are associated to the Boolean <code>True</code>.</li>
<li>The empty string <code>''</code> is associated to the Boolean <code>False</code>.</li>
</ul>
<p>Roughly speaking, each time a Boolean value is expected, you can throw in a Python object instead. The Python object will then be converted to a Boolean value. This Boolean value will be used to decide whether to enter, say, a <code>while</code> loop or an <code>if</code> statement. This is called <strong><em>“type flexibility”</em></strong> and it’s one of Python’s core design choices.</p>
<p>Per default, all objects are considered <code>True</code> if they are semantically non-empty. Empty objects are usually associated to the Boolean <code>False</code>. More specifically, only if one of the two cases is met, will the result of an object be <code>False</code>: (i) the <code>__len__()</code> function returns 0, or (ii) the <code>__bool__()</code> function returns <code>False</code>. You can redefine those two methods for each object.</p>
<p>From the <a href="https://docs.python.org/3/library/stdtypes.html#truth-value-testing" target="_blank" rel="noreferrer noopener">Python documentation</a>, here are some common objects that are associated to the Boolean <code>False</code>:</p>
<ul>
<li>Defined constants: <code>None</code> and <code>False</code>.</li>
<li>Zero of numerical types: <code>0</code>, <code>0.0</code>, <code>0j</code>, <code>Decimal(0)</code>, <code>Fraction(0, 1)</code></li>
<li>Empty iterables: <code>''</code>, <code>()</code>, <code>[]</code>, <code>{}</code>, <code>set()</code>, <code>range(0)</code></li>
</ul>
<p>Here are some examples:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">if []: print('1') if (): print('2') if [()]: print('3')
# 3 if 0: print('4') if 0.00: print('5') if 0.001: print('6')
# 6 if set(): print('7') if [set()]: print('8')
# 8</pre>
<p>Again, even if the iterable contains only a single element (that may evaluate to <code>False</code> like integer <code>0</code>), the implicit Boolean conversion will return <code>True</code> because an empty element is an element nonetheless.</p>
<h2>PEP8 Recommendation: How to Check if a List is Empty</h2>
<p>As some readers argued with me about how to correctly check for an empty list in Python, <a rel="noreferrer noopener" href="https://www.python.org/dev/peps/pep-0008/" target="_blank">here</a>‘s the explicit excerpt from the PEP8 standard (Python’s set of rules about how to write readable code):</p>
<p><em>For sequences, (strings, lists, tuples), use the fact that empty sequences are false:</em></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Correct:
if not seq:
if seq:</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Wrong:
if len(seq):
if not len(seq):</pre>
<h2>Performance Evaluations</h2>
<p>To see which of the three methods is fastest, I repeated each method 100 times using the <code>timeit</code> library on my notebook with Intel Core i7 ™ CPU of 8th Generation, 8GB RAM—yes, I know—and NVIDIA Graphic Card (not that it mattered).</p>
<p>Here’s the code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import timeit
import numpy as np setup = 'a = []' method1 = 'if len(a) == 0: pass'
method2 = 'if a == []: pass'
method3 = 'if not a: pass' t1 = timeit.repeat(stmt=method1, setup=setup, repeat=100)
t2 = timeit.repeat(stmt=method2, setup=setup, repeat=100)
t3 = timeit.repeat(stmt=method3, setup=setup, repeat=100) print('Method 1: len(a) == 0')
print('avg: ' + str(np.average(t1)))
print('var: ' + str(np.var(t1)))
print() print('Method 2: a == []')
print('avg: ' + str(np.average(t2)))
print('var: ' + str(np.var(t2)))
print() print('Method 3: not a')
print('avg: ' + str(np.average(t3)))
print('var: ' + str(np.var(t3)))
print()</pre>
<p>The third method is the most Pythonic one with type flexibility. We measure the elapsed time of 100 executions of each method. In particular, we’re interested in the average time and the variance of the elapsed time. Both should be minimal.</p>
<p>Our thesis is that the third, most Pythonic method is also the fastest because there’s no need to create a new empty list (like in method 2) or performing nested function calls like in method 1. Method 3 consists only of a single function call: converting the list into a Boolean value with the <code>__bool__</code> or <code>__len__</code> methods.</p>
<p>Here’s the result in terms of elapsed average runtime and variance of the runtimes:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Method 1: len(a) == 0
avg: 0.06273576400000003
var: 0.00022597495215430347 Method 2: a == []
avg: 0.034635367999999944
var: 8.290137682917488e-05 Method 3: not a
avg: 0.017685209000000004
var: 6.900910317342067e-05
</pre>
<p>You can see that the third method is not only 50% faster than method 2 and 75% faster than method 3, it also has very little variance. It’s clearly the best method in terms of runtime performance. Being also the shortest method, you can now see why the method is considered to be most “Pythonic”. </p>
<h2>Where to Go From Here?</h2>
<p>Enough theory, let’s get some practice!</p>
<p>To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?</p>
<p><strong>Practice projects is how you sharpen your saw in coding!</strong></p>
<p>Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?</p>
<p>Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.</p>
<p>Join my free webinar <a rel="noreferrer noopener" href="https://blog.finxter.com/webinar-freelancer/" target="_blank">“How to Build Your High-Income Skill Python”</a> and watch how I grew my coding business online and how you can, too—from the comfort of your own home.</p>
<p><a href="https://blog.finxter.com/webinar-freelancer/" target="_blank" rel="noreferrer noopener">Join the free webinar now!</a></p>
</div>


https://www.sickgaming.net/blog/2020/05/...-is-empty/
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016