{"id":550,"date":"2021-07-01T11:54:11","date_gmt":"2021-07-01T10:54:11","guid":{"rendered":"https:\/\/glennrowe.net\/programmingpages\/?p=550"},"modified":"2021-07-02T10:49:53","modified_gmt":"2021-07-02T09:49:53","slug":"generator-functions-and-the-yield-statement","status":"publish","type":"post","link":"https:\/\/glennrowe.net\/programmingpages\/2021\/07\/01\/generator-functions-and-the-yield-statement\/","title":{"rendered":"Generator functions and the yield statement"},"content":{"rendered":"<p>A normal function in Python can be terminated with a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">return<\/code> statement, which may or may not return a value back to the statement that called the function. After executing a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">return<\/code>, the function&#8217;s role in the program is over, at least until the next time the function is called. This means that the state of the function and all its local variables are deleted from memory.<\/p>\n<p>In some cases, it would be useful to have a function that can return a sequence of intermediate results, with the state of the function being retained between each of these results. Such a function is called a\u00a0<em>generator function<\/em>.<\/p>\n<p>It&#8217;s easiest to understand how a generator function works by looking at a specific example. Suppose we would like to generate the sequence of prime numbers from the smallest such number (2) up to some maximum value. To do this, we need an algorithm for generating all the prime numbers in a given range. The easiest way of doing this is to use a version of the famous algorithm known as the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Sieve_of_Eratosthenes\">sieve of Eratosthenes<\/a>. The algorithm we&#8217;ll use is as follows.<\/p>\n<p>First, recall that a prime number is an integer that is divisible only by itself and 1. An integer which is not prime is known as\u00a0<em>composite<\/em>, and any composite number must be divisible by at least one prime number. This prime divisor must be less than or equal to the square root of the composite number. One other useful observation is that 2 is the only even prime, so after listing 2 as a prime, we need to examine only odd numbers. With that in mind, here&#8217;s the code for generating the prime numbers from 2 up to some value max.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">from math import sqrt, floor\r\n\r\ndef genPrimes(max):\r\n    primes = [2]\r\n    yield 2\r\n\r\n    for n in range(3, max + 1, 2):\r\n        maxCheck = floor(sqrt(n))\r\n        isPrime = True\r\n        for fac in primes[1:]:\r\n            if fac &gt; maxCheck: break\r\n            if n % fac == 0:\r\n                isPrime = False\r\n                break\r\n        if isPrime:\r\n            primes += [n]\r\n            yield n<\/pre>\n<p>On line 4, we define the list <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">primes<\/code> which will contain the prime numbers. <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">primes<\/code> is initialized to 2, which is the first prime number. We&#8217;ll get to the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> statement in a minute.<\/p>\n<p>Next, we need to find all the primes larger than 2 but less than or equal to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">max<\/code>, so we use the loop over <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code> on line 7 to do this. The loop runs from 3 up to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">max<\/code> (remember that the second argument of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">range()<\/code> is one more than its final value), in steps of 2, since we&#8217;re skipping even numbers.<\/p>\n<p>The integer <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">maxCheck<\/code> is the largest integer that is less than or equal to the square root of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code>. If <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code> is composite, it must have at least one prime factor in the range from 3 up to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">maxCheck<\/code>. The loop on line 10 runs over the prime numbers in the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">primes<\/code> list, skipping <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">primes[0]<\/code> which is 2 and cannot be a factor of an odd number. If the number <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">fac<\/code> is larger than <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">maxCheck<\/code>, we break out of the loop. Otherwise, we check whether <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">fac<\/code> divides <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code>, and if so, we know that <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code> is composite so we can again break out of the loop. If none of the primes divides <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code>, then <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code> is prime and we add it to the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">primes<\/code> list on line 16.<\/p>\n<p>This algorithm (without the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> statements) would create the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">primes<\/code> list containing all the primes from 2 up to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">max<\/code>, so we could just return this list at the end of the function and then use the list in some other part of the program. However, we have written <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> so that it will &#8216;yield&#8217; the primes one at a time. Let&#8217;s see how this works.<\/p>\n<p>The first time <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> is called, it runs up to line 5 where the first <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> statement is found. At this point, the function sends the value 2 back to the statement that called <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code>. However, unlike a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">return<\/code> statement, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> does not end the function. Rather, the function&#8217;s state, and all its internal variables, are retained.<\/p>\n<p>After the calling statement does whatever it needs to with the yielded value, it can call the same instance of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> again. This time, execution of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> will pick up where it left off after the previous <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code>, so it will now start running at line 7, with the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop.<\/p>\n<p>The code in the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop will run and determine the next prime number, which is 3. When execution reaches line 17, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code> will be 3 and another <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> statement is encountered. This time, the value of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code> (3) is sent back to the calling statement. The process continues until the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop on line 7 finishes.<\/p>\n<p>If an attempt to call <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> is made after all the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> statements in the function have been run, a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">StopIteration<\/code> exception is raised. Depending on how <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> is being called, this might terminate the program, or it may be handled cleanly by the calling statement. The important point is that the function itself is not shut down until after the final <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> has been run.<\/p>\n<p>To get an idea of how a generator function can be used, we&#8217;ll add the following code after the function above (both code blocks can be placed in the same file):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">lastPrime = 2\r\nnumPrimes = 1\r\ngapStats = {}\r\nmax = input('Enter largest number: ')\r\n\r\nfor n in genPrimes(int(max)):\r\n    numPrimes += 1\r\n    gap = n - lastPrime\r\n    if gap in gapStats:\r\n        gapStats[gap] += 1\r\n    else:\r\n        gapStats[gap] = 1\r\n    lastPrime = n\r\nsortGaps = sorted(gapStats.items())\r\nprint(f'Number of primes: {numPrimes}' + '\\n', sortGaps)\r\n<\/pre>\n<p>This code will use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> to generate a sequence of primes, and then count the number of primes generated, and also count the frequencies of the various gaps between successive primes. The data on the frequencies of gaps are stored in a dictionary called <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">gapStats<\/code>.<\/p>\n<p>The call to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> is made in the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop on line 6. A <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop requires an iterator over which it can perform its loop, and the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> generator function serves as an iterator (Technically a generator is actually a subclass of an iterator, so it&#8217;s a type of iterator. Thus all generators are iterators, but the converse is not true.) Each time we run through the loop, the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> function is called, so it generates a sequence of primes that are sent back to the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop. Thus each <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> generates a value that is placed in the for loop&#8217;s variable <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">n<\/code>, which is then used to increment the count <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">numPrimes<\/code>, and to calculate the gap between the current prime and the previous prime, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">lastPrime<\/code>, and update the counts in the dictionary.<\/p>\n<p>A for loop contains an implicit handler for the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">StopIteration<\/code> exception, so once all the yields from <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> have run, the loop receives a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">StopIteration<\/code> and ends. After this, we sort the items in the dictionary on line 14 and print out the results.<\/p>\n<p>A couple of important points should be noted here. First, the call to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> on line 6 above produces a specific instance of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> generator. In order to access the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> statements within the generator sequentially, we must access the\u00a0<em>same<\/em> instance of the function. The <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop does this automatically; the instance of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> in line 6 is retained from one iteration of the loop to the next, so the yields are called sequentially.<\/p>\n<p>The other important point is that the program must provide a way of dealing with the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">StopIteration<\/code> exception that is generated after the last <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> is run. As mentioned above, a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop does this automatically, but if you use a generator somewhere else in your program, you may need to provide an explicit way of catching this exception.<\/p>\n<h2>The next() method<\/h2>\n<p>To illustrate these points, we&#8217;ll consider using <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> without a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop. We replace the second block of code above with this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">gp = genPrimes(10)\r\nwhile True:\r\n    print(next(gp), ' ', end = '')<\/pre>\n<p>The first line creates a specific instance of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">genPrimes()<\/code> and stores this in the variable <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">gp<\/code>. The <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">while<\/code> loop iterates over this generator by using the built-in\u00a0 <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">next()<\/code> method. Each time <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">next()<\/code> is called, the generator runs up to its next <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> statement and then returns the value at that point. Thus this loop generates all the primes between 2 and 10.<\/p>\n<p>However, if we use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">next()<\/code> to access successive yields, there is no handler in place to deal with the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">StopIteration<\/code> exception after all the yields have run. If we run the above code, we get the output:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">2  3  5  7  Traceback (most recent call last):\r\n  File \"D:\\Documents\\Programming\\programmingpages\\Python\\Primes 01\\Primes 01\\Primes_01.py\", line 3, in &lt;module&gt;\r\n    print(next(gp), ' ', end = '')\r\nStopIteration<\/pre>\n<p>The four primes less than 10 are printed, but then the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">StopIteration<\/code> causes an error which stops the program. We can add a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">try<\/code> block to <a href=\"https:\/\/glennrowe.net\/programmingpages\/2021\/06\/24\/handling-errors-with-exceptions\/\">handle the exception<\/a>, as in:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">gp = genPrimes(10)\r\ntry:\r\n    while True:\r\n        print(next(gp), ' ', end = '')\r\nexcept StopIteration:\r\n    print('\\nAll primes found')<\/pre>\n<p>Now we get the output:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">2  3  5  7\r\nAll primes found<\/pre>\n<h2>Exercise<\/h2>\n<p>Write a generator function that generates the Fibonacci sequence as an infinite sequence (that is, the function will keep generating values, no matter how many times it is called). The Fibonacci sequence <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-7f9d10af3355ac97a7c7fbc8a8396919_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#102;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"17\" style=\"vertical-align: -4px;\"\/> is defined as<\/p>\n<p class=\"ql-center-displayed-equation\" style=\"line-height: 16px;\"><span class=\"ql-right-eqno\"> &nbsp; <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-71495568cb8d417c7e8834069be846cd_l3.png\" height=\"16\" width=\"132\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#091; &#102;&#95;&#123;&#110;&#43;&#49;&#125;&#61;&#102;&#95;&#123;&#110;&#125;&#43;&#102;&#95;&#123;&#110;&#45;&#49;&#125; &#92;&#093;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p>\n<p>with <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-bc7fa2bfc4757c2feb47130dbfb9c861_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#102;&#95;&#49;&#61;&#102;&#95;&#50;&#61;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"88\" style=\"vertical-align: -4px;\"\/>. That is, each term is the sum of the previous two terms. [Some definitions of the sequence start with <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-6de9d4abff4476abf0e20de4093183ca_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#102;&#95;&#49;&#61;&#48;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"49\" style=\"vertical-align: -4px;\"\/> and <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-42a0415852c8ec80f459746198650501_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#102;&#95;&#50;&#61;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"48\" style=\"vertical-align: -4px;\"\/>, but for our purposes it&#8217;s easier to take the first two terms as 1.]\n<p>Use this generator to test the theorem that the ratio of two adjacent Fibonacci numbers tends to the Golden Ratio, which is defined as <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-5f65b82b47d754fed45df7ed0260ed76_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#112;&#104;&#105;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#43;&#92;&#115;&#113;&#114;&#116;&#123;&#53;&#125;&#125;&#123;&#50;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"25\" width=\"72\" style=\"vertical-align: -6px;\"\/>. That is, test that the following is true:<\/p>\n<p class=\"ql-center-displayed-equation\" style=\"line-height: 44px;\"><span class=\"ql-right-eqno\"> &nbsp; <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-422a82168f8ef756d3b62a927d138b09_l3.png\" height=\"44\" width=\"193\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#091; &#92;&#108;&#105;&#109;&#95;&#123;&#110;&#92;&#114;&#105;&#103;&#104;&#116;&#97;&#114;&#114;&#111;&#119;&#92;&#105;&#110;&#102;&#116;&#121;&#125;&#92;&#102;&#114;&#97;&#99;&#123;&#102;&#95;&#123;&#110;&#125;&#125;&#123;&#102;&#95;&#123;&#110;&#45;&#49;&#125;&#125;&#61;&#92;&#112;&#104;&#105;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#43;&#92;&#115;&#113;&#114;&#116;&#123;&#53;&#125;&#125;&#123;&#50;&#125; &#92;&#093;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p>\n<p>As <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-5b2be26c0c1341f54b29baddda771346_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#112;&#104;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"11\" style=\"vertical-align: -4px;\"\/> is an irrational number, you won&#8217;t be able to\u00a0<em>prove<\/em> that this limit is true, but you can verify it to a given precision. Your code should ask the user for a tolerance value (see <a href=\"https:\/\/glennrowe.net\/programmingpages\/2021\/04\/26\/floats-and-the-math-library-in-python\/\">this post<\/a> for a refresher on tolerances in floating point numbers) and then iterate through the generator until this precision is reached. At this point, you should print out the value of <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-968f595ccec399f60e3a6549465087cc_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#102;&#114;&#97;&#99;&#123;&#102;&#95;&#123;&#110;&#125;&#125;&#123;&#102;&#95;&#123;&#110;&#45;&#49;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"26\" width=\"31\" style=\"vertical-align: -9px;\"\/>, the value of <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-5b2be26c0c1341f54b29baddda771346_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#112;&#104;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"11\" style=\"vertical-align: -4px;\"\/>, and the number of Fibonacci numbers at which the tolerance was reached.<\/p>\n<span class=\"collapseomatic \" id=\"id69f59eceb4bcf\"  tabindex=\"0\" title=\"See answers\"    >See answers<\/span><span id='swap-id69f59eceb4bcf'  class='colomat-swap' style='display:none;'>Hide answers<\/span><div id=\"target-id69f59eceb4bcf\" class=\"collapseomatic_content \">\n<p>The program is as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">from math import *\r\n\r\ndef fibon():\r\n    fnm1 = 1\r\n    yield fnm1\r\n    fn = 1\r\n    yield fn\r\n    while True:\r\n        fnp1 = fnm1 + fn\r\n        yield fnp1\r\n        fnm1 = fn\r\n        fn = fnp1\r\n\r\nphi = (1 + sqrt(5))\/2\r\ntol = input('Tolerance: ')\r\ntol = float(tol)\r\ngenFibon = fibon()\r\nf1 = next(genFibon)\r\ncount = 1\r\nfor f2 in genFibon:\r\n    count += 1\r\n    ratio = f2 \/ f1\r\n    if isclose(ratio, phi, rel_tol=tol): break \r\n    f1 = f2\r\n\r\nprint(f'Ratio = {ratio}; Phi = {phi}; Count = {count}')<\/pre>\n<p>The <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">fibon()<\/code> function on line 3 takes no arguments, as it generates an infinite sequence of values. We specify the first two values as <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">fnm1 = 1<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">fn = 1<\/code>, and include a specific <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> for each of these values. The infinite loop on line 8 generates the sequence using the formula above by adding together the two previous values to get the next one, with a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">yield<\/code> after each value is calculated.<\/p>\n<p>The main program sets up the required values, and then creates an instance of the generator on line 17. As we need two Fibonacci numbers to calculate a ratio, we use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">next()<\/code> to get the first number on line 18, then enter a loop on line 20. The <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop calls successive Fibonacci numbers from the generator, calculates the ratio, and compares this with <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-5b2be26c0c1341f54b29baddda771346_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#112;&#104;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"11\" style=\"vertical-align: -4px;\"\/> using the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">isclose()<\/code> method we met when discussing <a href=\"https:\/\/glennrowe.net\/programmingpages\/2021\/04\/26\/floats-and-the-math-library-in-python\/\">floating point numbers<\/a>. If the required tolerance has been met, we break out of the loop and print the results.<\/p>\n<p>This program is a bit risky, since if the required tolerance is never met, the program will be in an infinite loop, so we should probably include some safeguards to cope with this situation. For example, we could break out of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for<\/code> loop if <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">count<\/code> exceeded some value. However, you&#8217;ll find that the result converges surprisingly quickly. The ratio is equal to <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-5b2be26c0c1341f54b29baddda771346_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#112;&#104;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"11\" style=\"vertical-align: -4px;\"\/> within a tolerance of <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/glennrowe.net\/programmingpages\/wp-content\/ql-cache\/quicklatex.com-5d8b7dbffb53b3fc521d5c5106c782ea_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#49;&#48;&#94;&#123;&#45;&#49;&#48;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"42\" style=\"vertical-align: 0px;\"\/> after only 26 Fibonacci numbers have been generated.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>A normal function in Python can be terminated with a return statement, which may or may not return a value back to the statement that called the function. After executing a return, the function&#8217;s role in the program is over, at least until the next time the function is called. This means that the state [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-550","post","type-post","status-publish","format-standard","hentry","category-python","entry"],"_links":{"self":[{"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/posts\/550","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/comments?post=550"}],"version-history":[{"count":6,"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/posts\/550\/revisions"}],"predecessor-version":[{"id":560,"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/posts\/550\/revisions\/560"}],"wp:attachment":[{"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/media?parent=550"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/categories?post=550"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/glennrowe.net\/programmingpages\/wp-json\/wp\/v2\/tags?post=550"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}