10-09-2020, 03:13 PM
Yield Keyword in Python – A Simple Illustrated Guide
<div><h2>Introduction To <strong>yield</strong> In Python</h2>
<p>While using a function, we generally use the <code>return</code> <a href="https://blog.finxter.com/python-cheat-sheet/" target="_blank" rel="noreferrer noopener">keyword </a>to return a value computed by the function. Similarly, the <code>yield</code> keyword also returns a value from a function, but it also maintains the state of the local variables inside the function and when the function is reused in the program, the execution of the function begins from the state of the <code>yield</code> statement that was executed in the previous function call. </p>
<p><strong>Example:</strong></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="">def counter(): x = 1 while x <= 5: yield x x += 1 for y in counter(): print(y)</pre>
<p><strong>Output:</strong></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="">1
2
3
4
5</pre>
<p>To understand the usage of yield keyword, you have to understand what are:</p>
<ul>
<li>Iterables</li>
<li>Generators </li>
</ul>
<p>So let us discuss generators and Iterables before diving into the <code>yield </code>keyword.</p>
<h2>Iterables</h2>
<p>An <strong>iterable </strong>is an object in Python from which we can get an iterator. For example, when a list is created, all its items can be iterated one by one. Thus, reading the items of the list one by one is known as iteration while the list is iterable. In Python, string, <a href="https://blog.finxter.com/python-lists/" target="_blank" rel="noreferrer noopener">lists</a>, <a href="https://blog.finxter.com/sets-in-python/" target="_blank" rel="noreferrer noopener">sets</a>, <a href="https://blog.finxter.com/the-ultimate-guide-to-python-tuples/" target="_blank" rel="noreferrer noopener">tuples</a>, and <a href="https://blog.finxter.com/python-dictionary/" target="_blank" rel="noreferrer noopener">dictionaries </a>are iterable containers from which we can get an iterator.</p>
<p><strong>Example:</strong></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="">name = "FINXTER"
li = [1,2,3]
tup = (4,5,6)
s = {"A","B","C"}
d = {"a":100,"b":200,"c":300} print("\nIterating over String:")
for x in name: print(x, end=", ")
print("\nIterating over list:")
for x in li: print(x, end=" ")
print("\nIterating over tuple:")
for x in tup: print(x, end=" ")
print("\nIterating over set:")
for x in s: print(x, end=" ")
print("\nIterating over dictionary:")
for x in d: print(d[x], end=" ")</pre>
<p><strong>Output:</strong></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="">Iterating over String:
F, I, N, X, T, E, R, Iterating over list:
1 2 3 Iterating over tuple:
4 5 6 Iterating over set:
A C B Iterating over dictionary:
100 200 300</pre>
<p>So we know, what is an iterable object. But what is an iterator?</p>
<h3>❖ <strong>Iterator</strong></h3>
<p>Simply put, an iterator is any object that can be iterated upon. Iterators are implemented using loops. </p>
<p><strong>Iterators implement the following methods which are known as <span style="color:#ff6900" class="has-inline-color">iterator protocols</span>:</strong></p>
<ul>
<li>__iter__() : returns the iterator object.</li>
<li>__next__()<strong> </strong>: allows us to perform operations and returns the next item in the sequence.</li>
</ul>
<p>Let us have a look at the following program how we can iterate through an iterator in Python using the iterator protocol.</p>
<p><strong>Example: </strong>Returning an iterator from a list(iterable) and printing each value one by one:</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="">li = [1,2,3,4,5]
it = iter(li) print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))</pre>
<p><strong>Output:</strong></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="">1
2
3
4
5</pre>
<p>Now that brings us to the question, what’s the difference between an iterator and iterable?</p>
<p>Here’s a one-liner to answer that:</p>
<blockquote class="wp-block-quote">
<p> <span style="color:#cf2e2e" class="has-inline-color">Every <strong>Iterator </strong>is an <strong>iterable</strong>, but every <strong>iterable </strong>is not an <strong>iterator</strong>.</span></p>
</blockquote>
<p>For example, a list is an iterable but it is not an iterator. We can create an iterator from an iterable object using the iterable object as shown above. </p>
<h3>❖ <strong>Creating Iterator Objects</strong></h3>
<p>As mentioned earlier, the <code>__iter__() </code>and<code> __next__()</code> methods have to be implemented in an object/class to make it an iterator. </p>
<p><strong>Example: </strong>The following program demonstrates the creation of an iterator that returns a sequence of numbers starting from 100 and each iteration will increase the value by 100.</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="">class IterObj: def __iter__(self): self.value = 100 return self def __next__(self): x = self.value self.value += 100 return x obj = IterObj()
it = iter(obj) print(next(it))
print(next(it))
print(next(it))</pre>
<p><strong>Output:</strong></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="">100
200
300</pre>
<p>The above program will continue to print forever if you keep using the <code>next()</code> statements. There must be a way to stop the iteration to go on forever. This is where the <code><span style="color:#cf2e2e" class="has-inline-color">StopIteration </span></code>statement comes into use.</p>
<h3>❖ <strong>StopIteration</strong></h3>
<p>Once the iteration is done for a specific number of times, we can define a terminating condition that raises an error once the desired number of iterations are over. This terminating condition is given by the <strong>StopIteration </strong>statement.</p>
<p><strong>Example:</strong></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="">class IterObj: def __iter__(self): self.value = 100 return self def __next__(self): if self.value <= 500: x = self.value self.value += 100 return x else: raise StopIteration obj = IterObj()
it = iter(obj) for a in it: print(a)</pre>
<p><strong>Output:</strong></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="">100
200
300
400
500</pre>
<h2>Generators</h2>
<p>While using iterators, we learned that we need to implement <code>__iter__()</code> and <code>__next__()</code> methods along and raise <code>StopIteration</code> to keep track of the number of the iterations. This can be quite lengthy and this is where generators come to our rescue. All the procedures that need to be followed while using iterators are automatically handled by generators.</p>
<p><strong>Generators </strong>are simple functions used to create iterators and return an iterable set of items, one value at a time. </p>
<p><img src="https://s.w.org/images/core/emoji/13.0.0/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> You can iterate over generators only once. Let us have a look at this in a program. </p>
<p><strong>Example 1: </strong>Using an iterator to iterate over the values twice.</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="">it = [x for x in range(6)]
print("Iterating over generator")
for i in it: print(i, end=", ")
print("\nIterating again!")
for j in it: print(j, end=", ")</pre>
<p><strong>Output:</strong></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="">Iterating over generator
0, 1, 2, 3, 4, 5, Iterating again!
0, 1, 2, 3, 4, 5,</pre>
<p><strong>Example 2: </strong>Using generator to iterate over values. ( The generator can be used only once, as shown in the output.)</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="">gen = (x for x in range(6))
print("Iterating over generator")
for i in gen: print(i, end=", ")
print("\nTrying to Iterate over the generator again!")
for j in gen: print(j, end=", ")</pre>
<p><strong>Output:</strong></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="">Iterating over generator
0, 1, 2, 3, 4, 5, Trying to Iterate over the generator again!</pre>
<p><img src="https://s.w.org/images/core/emoji/13.0.0/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Generators do not store all the values in the memory, instead, they generate the values on the fly. In the above example 2, the generator calculates and prints the value 0 and forgets it and then calculates and prints 1 and so on.</p>
<p>Now this brings us to our discussion on the <code>yield</code> keyword.</p>
<h2>The <strong><span style="color:#ff6900" class="has-inline-color">yield </span></strong>Keyword</h2>
<p>As mentioned earlier, <code>yield</code> is a keyword similar to the <code>return</code> keyword, but in case of <code>yield</code> the function returns a generator. </p>
<p><strong>Example: </strong>The following uses a generator function that yields 7 random integers between 1 and 99.</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="">from random import randint def game(): # returns 6 numbers between 1 and 50 for i in range(6): yield randint(1, 50) # returns a 7th number between 51 and 99 yield randint(51,99) for random_no in game(): print("Lucky Number : ", (random_no))</pre>
<p><strong>Output:</strong></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=""> Lucky Number : 12 Lucky Number : 12 Lucky Number : 47 Lucky Number : 36 Lucky Number : 28 Lucky Number : 25 Lucky Number : 55</pre>
<p>In the above program the generator function <code>game()</code> generates 6 random integers between 1 and 50 by executing the <code>yield</code> statement one at a time and finally generates the 7th random number between 51 and 99 by executing the yield outside the loop. </p>
<p><img src="https://s.w.org/images/core/emoji/13.0.0/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Note: </strong>When the function is called, the code within the function body does not run. Instead, the function body simply returns the generator object, and then the code will continue from where it left off each time the <code>for</code> loop uses the generator. Tricky!!! Isn’t it? <img src="https://s.w.org/images/core/emoji/13.0.0/72x72/1f609.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Let us discuss the workflow to make things a little simple:</p>
<ol>
<li>When the <code>for loop</code> is used for the first time, it calls the generator object created from the function. It runs the code in the function from the beginning until it hits <code>yield</code>. </li>
<li>Then it returns the first value in the loop.</li>
<li>Then each subsequent function call runs another iteration of the loop inside the function and returns the next value. </li>
<li>This continues until the generator is empty, that is when the function runs without an <code>yield</code> statement. This happens when the loop is exhausted or the <code>if-else</code> condition is no longer met.</li>
</ol>
<p><strong>Things To Remember:</strong></p>
<ul>
<li>Since yield stores the state of local variables, overhead of memory allocation is controlled.</li>
<li>This also ensures that the program control flow doesn’t start from the beginning all over again, thereby saving time.</li>
<li>However, time and memory optimization can make the code complex to grasp.</li>
</ul>
<h3><strong>Comparing Time And Memory Optimization For Iterator Functions Vs Generators</strong></h3>
<p><strong>Example 1: </strong>The program given below computes the time and memory usage while using a function with an iterator. </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 time
import random
import os
import psutil mobile_name = ["iPhone 11", "iPhone XR", "iPhone 11 Pro Max"]
colors = ["red","black","grey"]
def mobile_list(ph): phones = [] for i in range(ph): phone = { 'name': random.choice(mobile_name), 'color': random.choice(colors) } colors.append(phone) return phones # Calculate time of processing
t1 = time.time()
cars = mobile_list(1000000)
t2 = time.time()
print('Took {} seconds'.format(t2-t1)) # Calculate Memory used
process = psutil.Process(os.getpid())
print('Memory used: ' + str(process.memory_info().rss/1000000))</pre>
<p><strong>output:</strong></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="">Took 14.238950252532959 seconds
Memory used: 267.157504</pre>
<p><strong>Example 2: </strong>The following program uses a generator with the yield statement instead of a function and then we calculate the memory and time used in this case.</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 time
import random
import os
import psutil mobile_name = ["iPhone 11", "iPhone XR", "iPhone 11 Pro Max"]
colors = ["red","black","grey"]
def mobile_list(ph): for i in range(ph): phone = { 'name': random.choice(mobile_name), 'color': random.choice(colors) } yield phone # Calculate time of processing
t1 = time.time()
for car in mobile_list(1000000): pass
t2 = time.time()
print('Took {} seconds'.format(t2-t1)) # Calculate Memory used
process = psutil.Process(os.getpid())
print('Memory used: ' + str(process.memory_info().rss/1000000))</pre>
<p><strong>Output:</strong></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="">Took 7.272227048873901 seconds
Memory used: 15.663104</pre>
<p>The above examples clearly depict the superiority of generators and <code>yield </code>keyword over normal functions with <code>return </code>keyword.</p>
<p><strong>Disclaimer: </strong>You have to <code>pip install psutil</code> so that the code works in your machine. Further, the time and memory usage values returned will vary based on the specifications of the machine in use.</p>
<h2><strong>return </strong>Keyword vs <strong>yield </strong>Keyword </h2>
<p>Before we conclude our discussion, let us finish what we started and discuss the difference between the <code>yield </code>and <code>return </code>statements in Python.</p>
<figure class="wp-block-image size-large"><img loading="lazy" width="769" height="546" src="https://blog.finxter.com/wp-content/uploads/2020/10/image-109.png" alt="" class="wp-image-14748" srcset="https://blog.finxter.com/wp-content/uploads/2020/10/image-109.png 769w, https://blog.finxter.com/wp-content/uplo...00x213.png 300w, https://blog.finxter.com/wp-content/uplo...50x107.png 150w" sizes="(max-width: 769px) 100vw, 769px" /></figure>
<h2>Conclusion</h2>
<p>In this article we learned:</p>
<ul>
<li>What are Iterables?</li>
<li>What are Iterators?</li>
<li>The difference between Iterables and Iterators.</li>
<li>Creating Iterator Objects.</li>
<li>The <code>StopIteration</code> statement.</li>
<li>What are Generators in Python?</li>
<li>The Yield Keyword.</li>
<li>Comparing Time And Memory Optimization For Iterator Functions Vs Generators.</li>
<li>The difference between <code>return </code>and <code>yield </code>keywords.</li>
</ul>
<p>Here’s a small recap of the concepts that we learned in this article; please follow the slide show give below:</p>
<figure class="wp-block-image size-large"><img loading="lazy" width="640" height="362" src="https://blog.finxter.com/wp-content/uploads/2020/10/yield.gif" alt="" class="wp-image-14751" /></figure>
<p>Please <a href="https://blog.finxter.com/subscribe/" target="_blank" rel="noreferrer noopener">subscribe </a>and <a href="https://blog.finxter.com/" target="_blank" rel="noreferrer noopener">stay tuned</a> for more interesting articles!</p>
<h2 class="wp-block-block">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>
<p>The post <a href="https://blog.finxter.com/yield-keyword-in-python-a-simple-illustrated-guide/" target="_blank" rel="noopener noreferrer">Yield Keyword in Python – A Simple Illustrated Guide</a> first appeared on <a href="https://blog.finxter.com/" target="_blank" rel="noopener noreferrer">Finxter</a>.</p>
</div>
https://www.sickgaming.net/blog/2020/10/...ted-guide/
<div><h2>Introduction To <strong>yield</strong> In Python</h2>
<p>While using a function, we generally use the <code>return</code> <a href="https://blog.finxter.com/python-cheat-sheet/" target="_blank" rel="noreferrer noopener">keyword </a>to return a value computed by the function. Similarly, the <code>yield</code> keyword also returns a value from a function, but it also maintains the state of the local variables inside the function and when the function is reused in the program, the execution of the function begins from the state of the <code>yield</code> statement that was executed in the previous function call. </p>
<p><strong>Example:</strong></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="">def counter(): x = 1 while x <= 5: yield x x += 1 for y in counter(): print(y)</pre>
<p><strong>Output:</strong></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="">1
2
3
4
5</pre>
<p>To understand the usage of yield keyword, you have to understand what are:</p>
<ul>
<li>Iterables</li>
<li>Generators </li>
</ul>
<p>So let us discuss generators and Iterables before diving into the <code>yield </code>keyword.</p>
<h2>Iterables</h2>
<p>An <strong>iterable </strong>is an object in Python from which we can get an iterator. For example, when a list is created, all its items can be iterated one by one. Thus, reading the items of the list one by one is known as iteration while the list is iterable. In Python, string, <a href="https://blog.finxter.com/python-lists/" target="_blank" rel="noreferrer noopener">lists</a>, <a href="https://blog.finxter.com/sets-in-python/" target="_blank" rel="noreferrer noopener">sets</a>, <a href="https://blog.finxter.com/the-ultimate-guide-to-python-tuples/" target="_blank" rel="noreferrer noopener">tuples</a>, and <a href="https://blog.finxter.com/python-dictionary/" target="_blank" rel="noreferrer noopener">dictionaries </a>are iterable containers from which we can get an iterator.</p>
<p><strong>Example:</strong></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="">name = "FINXTER"
li = [1,2,3]
tup = (4,5,6)
s = {"A","B","C"}
d = {"a":100,"b":200,"c":300} print("\nIterating over String:")
for x in name: print(x, end=", ")
print("\nIterating over list:")
for x in li: print(x, end=" ")
print("\nIterating over tuple:")
for x in tup: print(x, end=" ")
print("\nIterating over set:")
for x in s: print(x, end=" ")
print("\nIterating over dictionary:")
for x in d: print(d[x], end=" ")</pre>
<p><strong>Output:</strong></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="">Iterating over String:
F, I, N, X, T, E, R, Iterating over list:
1 2 3 Iterating over tuple:
4 5 6 Iterating over set:
A C B Iterating over dictionary:
100 200 300</pre>
<p>So we know, what is an iterable object. But what is an iterator?</p>
<h3>❖ <strong>Iterator</strong></h3>
<p>Simply put, an iterator is any object that can be iterated upon. Iterators are implemented using loops. </p>
<p><strong>Iterators implement the following methods which are known as <span style="color:#ff6900" class="has-inline-color">iterator protocols</span>:</strong></p>
<ul>
<li>__iter__() : returns the iterator object.</li>
<li>__next__()<strong> </strong>: allows us to perform operations and returns the next item in the sequence.</li>
</ul>
<p>Let us have a look at the following program how we can iterate through an iterator in Python using the iterator protocol.</p>
<p><strong>Example: </strong>Returning an iterator from a list(iterable) and printing each value one by one:</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="">li = [1,2,3,4,5]
it = iter(li) print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))</pre>
<p><strong>Output:</strong></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="">1
2
3
4
5</pre>
<p>Now that brings us to the question, what’s the difference between an iterator and iterable?</p>
<p>Here’s a one-liner to answer that:</p>
<blockquote class="wp-block-quote">
<p> <span style="color:#cf2e2e" class="has-inline-color">Every <strong>Iterator </strong>is an <strong>iterable</strong>, but every <strong>iterable </strong>is not an <strong>iterator</strong>.</span></p>
</blockquote>
<p>For example, a list is an iterable but it is not an iterator. We can create an iterator from an iterable object using the iterable object as shown above. </p>
<h3>❖ <strong>Creating Iterator Objects</strong></h3>
<p>As mentioned earlier, the <code>__iter__() </code>and<code> __next__()</code> methods have to be implemented in an object/class to make it an iterator. </p>
<p><strong>Example: </strong>The following program demonstrates the creation of an iterator that returns a sequence of numbers starting from 100 and each iteration will increase the value by 100.</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="">class IterObj: def __iter__(self): self.value = 100 return self def __next__(self): x = self.value self.value += 100 return x obj = IterObj()
it = iter(obj) print(next(it))
print(next(it))
print(next(it))</pre>
<p><strong>Output:</strong></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="">100
200
300</pre>
<p>The above program will continue to print forever if you keep using the <code>next()</code> statements. There must be a way to stop the iteration to go on forever. This is where the <code><span style="color:#cf2e2e" class="has-inline-color">StopIteration </span></code>statement comes into use.</p>
<h3>❖ <strong>StopIteration</strong></h3>
<p>Once the iteration is done for a specific number of times, we can define a terminating condition that raises an error once the desired number of iterations are over. This terminating condition is given by the <strong>StopIteration </strong>statement.</p>
<p><strong>Example:</strong></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="">class IterObj: def __iter__(self): self.value = 100 return self def __next__(self): if self.value <= 500: x = self.value self.value += 100 return x else: raise StopIteration obj = IterObj()
it = iter(obj) for a in it: print(a)</pre>
<p><strong>Output:</strong></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="">100
200
300
400
500</pre>
<h2>Generators</h2>
<p>While using iterators, we learned that we need to implement <code>__iter__()</code> and <code>__next__()</code> methods along and raise <code>StopIteration</code> to keep track of the number of the iterations. This can be quite lengthy and this is where generators come to our rescue. All the procedures that need to be followed while using iterators are automatically handled by generators.</p>
<p><strong>Generators </strong>are simple functions used to create iterators and return an iterable set of items, one value at a time. </p>
<p><img src="https://s.w.org/images/core/emoji/13.0.0/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> You can iterate over generators only once. Let us have a look at this in a program. </p>
<p><strong>Example 1: </strong>Using an iterator to iterate over the values twice.</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="">it = [x for x in range(6)]
print("Iterating over generator")
for i in it: print(i, end=", ")
print("\nIterating again!")
for j in it: print(j, end=", ")</pre>
<p><strong>Output:</strong></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="">Iterating over generator
0, 1, 2, 3, 4, 5, Iterating again!
0, 1, 2, 3, 4, 5,</pre>
<p><strong>Example 2: </strong>Using generator to iterate over values. ( The generator can be used only once, as shown in the output.)</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="">gen = (x for x in range(6))
print("Iterating over generator")
for i in gen: print(i, end=", ")
print("\nTrying to Iterate over the generator again!")
for j in gen: print(j, end=", ")</pre>
<p><strong>Output:</strong></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="">Iterating over generator
0, 1, 2, 3, 4, 5, Trying to Iterate over the generator again!</pre>
<p><img src="https://s.w.org/images/core/emoji/13.0.0/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Generators do not store all the values in the memory, instead, they generate the values on the fly. In the above example 2, the generator calculates and prints the value 0 and forgets it and then calculates and prints 1 and so on.</p>
<p>Now this brings us to our discussion on the <code>yield</code> keyword.</p>
<h2>The <strong><span style="color:#ff6900" class="has-inline-color">yield </span></strong>Keyword</h2>
<p>As mentioned earlier, <code>yield</code> is a keyword similar to the <code>return</code> keyword, but in case of <code>yield</code> the function returns a generator. </p>
<p><strong>Example: </strong>The following uses a generator function that yields 7 random integers between 1 and 99.</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="">from random import randint def game(): # returns 6 numbers between 1 and 50 for i in range(6): yield randint(1, 50) # returns a 7th number between 51 and 99 yield randint(51,99) for random_no in game(): print("Lucky Number : ", (random_no))</pre>
<p><strong>Output:</strong></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=""> Lucky Number : 12 Lucky Number : 12 Lucky Number : 47 Lucky Number : 36 Lucky Number : 28 Lucky Number : 25 Lucky Number : 55</pre>
<p>In the above program the generator function <code>game()</code> generates 6 random integers between 1 and 50 by executing the <code>yield</code> statement one at a time and finally generates the 7th random number between 51 and 99 by executing the yield outside the loop. </p>
<p><img src="https://s.w.org/images/core/emoji/13.0.0/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Note: </strong>When the function is called, the code within the function body does not run. Instead, the function body simply returns the generator object, and then the code will continue from where it left off each time the <code>for</code> loop uses the generator. Tricky!!! Isn’t it? <img src="https://s.w.org/images/core/emoji/13.0.0/72x72/1f609.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Let us discuss the workflow to make things a little simple:</p>
<ol>
<li>When the <code>for loop</code> is used for the first time, it calls the generator object created from the function. It runs the code in the function from the beginning until it hits <code>yield</code>. </li>
<li>Then it returns the first value in the loop.</li>
<li>Then each subsequent function call runs another iteration of the loop inside the function and returns the next value. </li>
<li>This continues until the generator is empty, that is when the function runs without an <code>yield</code> statement. This happens when the loop is exhausted or the <code>if-else</code> condition is no longer met.</li>
</ol>
<p><strong>Things To Remember:</strong></p>
<ul>
<li>Since yield stores the state of local variables, overhead of memory allocation is controlled.</li>
<li>This also ensures that the program control flow doesn’t start from the beginning all over again, thereby saving time.</li>
<li>However, time and memory optimization can make the code complex to grasp.</li>
</ul>
<h3><strong>Comparing Time And Memory Optimization For Iterator Functions Vs Generators</strong></h3>
<p><strong>Example 1: </strong>The program given below computes the time and memory usage while using a function with an iterator. </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 time
import random
import os
import psutil mobile_name = ["iPhone 11", "iPhone XR", "iPhone 11 Pro Max"]
colors = ["red","black","grey"]
def mobile_list(ph): phones = [] for i in range(ph): phone = { 'name': random.choice(mobile_name), 'color': random.choice(colors) } colors.append(phone) return phones # Calculate time of processing
t1 = time.time()
cars = mobile_list(1000000)
t2 = time.time()
print('Took {} seconds'.format(t2-t1)) # Calculate Memory used
process = psutil.Process(os.getpid())
print('Memory used: ' + str(process.memory_info().rss/1000000))</pre>
<p><strong>output:</strong></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="">Took 14.238950252532959 seconds
Memory used: 267.157504</pre>
<p><strong>Example 2: </strong>The following program uses a generator with the yield statement instead of a function and then we calculate the memory and time used in this case.</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 time
import random
import os
import psutil mobile_name = ["iPhone 11", "iPhone XR", "iPhone 11 Pro Max"]
colors = ["red","black","grey"]
def mobile_list(ph): for i in range(ph): phone = { 'name': random.choice(mobile_name), 'color': random.choice(colors) } yield phone # Calculate time of processing
t1 = time.time()
for car in mobile_list(1000000): pass
t2 = time.time()
print('Took {} seconds'.format(t2-t1)) # Calculate Memory used
process = psutil.Process(os.getpid())
print('Memory used: ' + str(process.memory_info().rss/1000000))</pre>
<p><strong>Output:</strong></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="">Took 7.272227048873901 seconds
Memory used: 15.663104</pre>
<p>The above examples clearly depict the superiority of generators and <code>yield </code>keyword over normal functions with <code>return </code>keyword.</p>
<p><strong>Disclaimer: </strong>You have to <code>pip install psutil</code> so that the code works in your machine. Further, the time and memory usage values returned will vary based on the specifications of the machine in use.</p>
<h2><strong>return </strong>Keyword vs <strong>yield </strong>Keyword </h2>
<p>Before we conclude our discussion, let us finish what we started and discuss the difference between the <code>yield </code>and <code>return </code>statements in Python.</p>
<figure class="wp-block-image size-large"><img loading="lazy" width="769" height="546" src="https://blog.finxter.com/wp-content/uploads/2020/10/image-109.png" alt="" class="wp-image-14748" srcset="https://blog.finxter.com/wp-content/uploads/2020/10/image-109.png 769w, https://blog.finxter.com/wp-content/uplo...00x213.png 300w, https://blog.finxter.com/wp-content/uplo...50x107.png 150w" sizes="(max-width: 769px) 100vw, 769px" /></figure>
<h2>Conclusion</h2>
<p>In this article we learned:</p>
<ul>
<li>What are Iterables?</li>
<li>What are Iterators?</li>
<li>The difference between Iterables and Iterators.</li>
<li>Creating Iterator Objects.</li>
<li>The <code>StopIteration</code> statement.</li>
<li>What are Generators in Python?</li>
<li>The Yield Keyword.</li>
<li>Comparing Time And Memory Optimization For Iterator Functions Vs Generators.</li>
<li>The difference between <code>return </code>and <code>yield </code>keywords.</li>
</ul>
<p>Here’s a small recap of the concepts that we learned in this article; please follow the slide show give below:</p>
<figure class="wp-block-image size-large"><img loading="lazy" width="640" height="362" src="https://blog.finxter.com/wp-content/uploads/2020/10/yield.gif" alt="" class="wp-image-14751" /></figure>
<p>Please <a href="https://blog.finxter.com/subscribe/" target="_blank" rel="noreferrer noopener">subscribe </a>and <a href="https://blog.finxter.com/" target="_blank" rel="noreferrer noopener">stay tuned</a> for more interesting articles!</p>
<h2 class="wp-block-block">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>
<p>The post <a href="https://blog.finxter.com/yield-keyword-in-python-a-simple-illustrated-guide/" target="_blank" rel="noopener noreferrer">Yield Keyword in Python – A Simple Illustrated Guide</a> first appeared on <a href="https://blog.finxter.com/" target="_blank" rel="noopener noreferrer">Finxter</a>.</p>
</div>
https://www.sickgaming.net/blog/2020/10/...ted-guide/