<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Yield on Haseeb Majid</title>
    <link>https://haseebmajid.dev/tags/yield/</link>
    <description>Recent content in Yield on Haseeb Majid</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Mon, 30 Nov 2020 00:00:00 +0000</lastBuildDate><atom:link href="https://haseebmajid.dev/tags/yield/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>What does yield do in Python</title>
      <link>https://haseebmajid.dev/posts/2020-11-30-what-does-yield-do-in-python/</link>
      <pubDate>Mon, 30 Nov 2020 00:00:00 +0000</pubDate>
      <author>Me</author>
      <guid>https://haseebmajid.dev/posts/2020-11-30-what-does-yield-do-in-python/</guid>
      <description>&lt;p&gt;In this article, we will go over what the &lt;code&gt;yield&lt;/code&gt; keyword is used for. We will also cover how you can use a &lt;code&gt;yield&lt;/code&gt;
with a pytest fixture to allow us to &amp;ldquo;teardown&amp;rdquo; tests, after all of our tests have run. A common job being removing
test data from the database, so that next time your run the tests your tests won&amp;rsquo;t fail. Due to the database being
in a different (unexpected) state.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In this article, we will go over what the <code>yield</code> keyword is used for. We will also cover how you can use a <code>yield</code>
with a pytest fixture to allow us to &ldquo;teardown&rdquo; tests, after all of our tests have run. A common job being removing
test data from the database, so that next time your run the tests your tests won&rsquo;t fail. Due to the database being
in a different (unexpected) state.</p>
<h2 id="background">Background</h2>
<h3 id="iterables--iterators">Iterables &amp; Iterators</h3>
<p>Before we can look at the <code>yield</code> keyword we will need to cover iterables and generators in Python. An &ldquo;iterable&rdquo; is
any Python object that can return its members one at a time, in a for-loop.</p>
<p>In Python we have functions called magic methods, there are methods like <code>__enter__</code> and <code>__exit__</code> defined within
objects. These are called &ldquo;magic&rdquo; methods because they are never directly called by the user. For an object to be
iterable, it needs to implement the <code>__iter__</code> method. If an object is iterable it can be passed to the <code>iter()</code>
function. The <code>iter()</code> function returns an iterator.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="err">❯</span> <span class="n">ipython</span>
</span></span><span class="line"><span class="cl"><span class="n">Python</span> <span class="mf">3.8.5</span> <span class="p">(</span><span class="n">default</span><span class="p">,</span> <span class="n">Jul</span> <span class="mi">28</span> <span class="mi">2020</span><span class="p">,</span> <span class="mi">12</span><span class="p">:</span><span class="mi">59</span><span class="p">:</span><span class="mi">40</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Type</span> <span class="s1">&#39;copyright&#39;</span><span class="p">,</span> <span class="s1">&#39;credits&#39;</span> <span class="ow">or</span> <span class="s1">&#39;license&#39;</span> <span class="k">for</span> <span class="n">more</span> <span class="n">information</span>
</span></span><span class="line"><span class="cl"><span class="n">IPython</span> <span class="mf">7.14.0</span> <span class="o">--</span> <span class="n">An</span> <span class="n">enhanced</span> <span class="n">Interactive</span> <span class="n">Python</span><span class="o">.</span> <span class="n">Type</span> <span class="s1">&#39;?&#39;</span> <span class="k">for</span> <span class="n">help</span><span class="o">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">1</span><span class="p">]:</span> <span class="nb">iter</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">Out</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span> <span class="o">&lt;</span><span class="n">list_iterator</span> <span class="n">at</span> <span class="mh">0x7f4c11556730</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="nb">iter</span><span class="p">(</span><span class="s2">&#34;hello&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Out</span><span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="o">&lt;</span><span class="n">str_iterator</span> <span class="n">at</span> <span class="mh">0x7f4c11598c10</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">3</span><span class="p">]:</span> <span class="nb">iter</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="o">---------------------------------------------------------------------------</span>
</span></span><span class="line"><span class="cl"><span class="ne">TypeError</span>                                 <span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">3</span><span class="o">-</span><span class="n">ef50b48e4398</span><span class="o">&gt;</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">----&gt;</span> <span class="mi">1</span> <span class="nb">iter</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="ne">TypeError</span><span class="p">:</span> <span class="s1">&#39;int&#39;</span> <span class="nb">object</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">iterable</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">4</span><span class="p">]:</span>
</span></span></code></pre></div><p>An iterator is any object which has the <code>__next__</code> magic method defined. Whenever we use a for-loop
(or list comprehension), the <code>next</code> method is called automatically for us, to get the next item from
the iterable.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">5</span><span class="p">]:</span> <span class="n">hello_list</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;h&#34;</span><span class="p">,</span> <span class="s2">&#34;e&#34;</span><span class="p">,</span> <span class="s2">&#34;l&#34;</span><span class="p">,</span> <span class="s2">&#34;l&#34;</span><span class="p">,</span> <span class="s2">&#34;o&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">6</span><span class="p">]:</span> <span class="n">iterator</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">hello_list</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">7</span><span class="p">]:</span> <span class="nb">next</span><span class="p">(</span><span class="n">iterator</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Out</span><span class="p">[</span><span class="mi">7</span><span class="p">]:</span> <span class="s1">&#39;h&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">8</span><span class="p">]:</span> <span class="nb">next</span><span class="p">(</span><span class="n">iterator</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Out</span><span class="p">[</span><span class="mi">8</span><span class="p">]:</span> <span class="s1">&#39;e&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">9</span><span class="p">]:</span> <span class="nb">next</span><span class="p">(</span><span class="n">iterator</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Out</span><span class="p">[</span><span class="mi">9</span><span class="p">]:</span> <span class="s1">&#39;l&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">10</span><span class="p">]:</span> <span class="nb">next</span><span class="p">(</span><span class="n">iterator</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Out</span><span class="p">[</span><span class="mi">10</span><span class="p">]:</span> <span class="s1">&#39;l&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">11</span><span class="p">]:</span> <span class="nb">next</span><span class="p">(</span><span class="n">iterator</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Out</span><span class="p">[</span><span class="mi">11</span><span class="p">]:</span> <span class="s1">&#39;o&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">12</span><span class="p">]:</span> <span class="nb">next</span><span class="p">(</span><span class="n">iterator</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="o">---------------------------------------------------------------------------</span>
</span></span><span class="line"><span class="cl"><span class="ne">StopIteration</span>                             <span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">12</span><span class="o">-</span><span class="mi">4</span><span class="n">ce711c44abc</span><span class="o">&gt;</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">----&gt;</span> <span class="mi">1</span> <span class="nb">next</span><span class="p">(</span><span class="n">iterator</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="ne">StopIteration</span><span class="p">:</span>
</span></span></code></pre></div><p>In summary, an iterable is an object that can be &ldquo;looped&rdquo; over and an iterator is an object which can
do the &ldquo;looping&rdquo; for us, it will keep track of the current state/index and move to the next item.
In the example above the <code>hello_list</code> is iterable and the <code>iterator</code> variable is the iterator.</p>
<h3 id="generators">Generators</h3>
<p>Generators are a special type of iterable, they differ from normal lists in two main ways:</p>
<ul>
<li>You can only iterate over them once</li>
<li>They don&rsquo;t store all of their values in memory</li>
</ul>
<p>So generators can be great when lists get very large.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">14</span><span class="p">]:</span> <span class="n">g</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="o">^</span><span class="mi">2</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">15</span><span class="p">]:</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">g</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"><span class="mi">2</span>
</span></span><span class="line"><span class="cl"><span class="mi">3</span>
</span></span><span class="line"><span class="cl"><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="mi">6</span>
</span></span><span class="line"><span class="cl"><span class="mi">7</span>
</span></span><span class="line"><span class="cl"><span class="mi">4</span>
</span></span><span class="line"><span class="cl"><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="mi">11</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">16</span><span class="p">]:</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">g</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>
</span></span></code></pre></div><h2 id="yield">Yield</h2>
<p>Now that we finally understand iterables and generators let&rsquo;s see how they relate to the <code>yield</code> keyword. <code>yield</code> can be
used like <code>return</code> except it will return a generator.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">17</span><span class="p">]:</span> <span class="k">def</span> <span class="nf">example</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="k">yield</span> <span class="s2">&#34;A&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="k">yield</span> <span class="s2">&#34;B&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="k">yield</span> <span class="s2">&#34;C&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">18</span><span class="p">]:</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">example</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"><span class="n">A</span>
</span></span><span class="line"><span class="cl"><span class="n">B</span>
</span></span><span class="line"><span class="cl"><span class="n">C</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">22</span><span class="p">]:</span> <span class="n">example</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">Out</span><span class="p">[</span><span class="mi">22</span><span class="p">]:</span> <span class="o">&lt;</span><span class="n">generator</span> <span class="nb">object</span> <span class="n">example</span> <span class="n">at</span> <span class="mh">0x7f4c1147a0b0</span><span class="o">&gt;</span>
</span></span></code></pre></div><p>A good example of <code>yield</code> can be seen above, it differs from a return because it is smart enough to retain &ldquo;state&rdquo;
and resume where it left off in the function. We can see the same example with <code>return</code>. In this example there is only
a single item being returned so only &ldquo;A&rdquo; is being looped over.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">19</span><span class="p">]:</span> <span class="k">def</span> <span class="nf">example</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="k">return</span> <span class="s2">&#34;A&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="k">return</span> <span class="s2">&#34;B&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="k">return</span> <span class="s2">&#34;C&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">In</span> <span class="p">[</span><span class="mi">20</span><span class="p">]:</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">example</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>     <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"><span class="n">A</span>
</span></span></code></pre></div><h2 id="pytest-example">Pytest Example</h2>
<p>One interesting use case of using the <code>yield</code> keyword is using it to run clean up tasks after running tests using
pytest. Pytest is a very popular testing framework in Python, it allows us to create a file called <code>conftest.py</code>.
Here we store common functions, fixtures shared between our tests.</p>
<p>In the example below, before any tests have run the <code>clean_up</code> fixture will be called, because we have given
it the <code>autouse=True</code> parameter. It will <code>yield</code>, and return a generator after all of our tests have finished
running. The print and the teardown tasks will then be run. This is useful for example when you want to clean up
your database after running tests that will add &ldquo;test&rdquo; data to it. Or in fact, any other type of teardown tasks
you need to run after all of your tests have finished running.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@pytest.fixture</span><span class="p">(</span><span class="n">scope</span><span class="o">=</span><span class="s2">&#34;session&#34;</span><span class="p">,</span> <span class="n">autouse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">clean_up</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">yield</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;teardown after yield&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">delete_database_collection</span><span class="p">()</span>
</span></span></code></pre></div><h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://realpython.com/python-for-loop/">Real Python</a> &ldquo;for&rdquo; loop</li>
<li><a href="https://realpython.com/introduction-to-python-generators/">Real Python</a> generators</li>
<li><a href="https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do">SO Post</a></li>
<li><a href="https://dzone.com/articles/when-to-use-yield-instead-of-return-in-python">DZone Yield vs Return</a></li>
</ul>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
