|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "metadata": {}, |
| 6 | + "source": [ |
| 7 | + "# Python Generators\n", |
| 8 | + "[documentation](https://docs.python.org/3/howto/functional.html#generators) \n", |
| 9 | + "[Another really good tutorial](https://realpython.com/introduction-to-python-generators/#using-generators)" |
| 10 | + ] |
| 11 | + }, |
| 12 | + { |
| 13 | + "cell_type": "markdown", |
| 14 | + "metadata": {}, |
| 15 | + "source": [ |
| 16 | + "*yield* keyword makes a function into a generator. Python keeps the call stack for the generator function open and saves the state. When you invoke the next() function it will return execution to the same point it left off in the generator function." |
| 17 | + ] |
| 18 | + }, |
| 19 | + { |
| 20 | + "cell_type": "markdown", |
| 21 | + "metadata": {}, |
| 22 | + "source": [ |
| 23 | + "### Simple generator function \n", |
| 24 | + "The while loop continues indefinitely. The function increments x then returns x with each iteration." |
| 25 | + ] |
| 26 | + }, |
| 27 | + { |
| 28 | + "cell_type": "code", |
| 29 | + "execution_count": 28, |
| 30 | + "metadata": {}, |
| 31 | + "outputs": [], |
| 32 | + "source": [ |
| 33 | + "def my_generator(x=1):\n", |
| 34 | + " while True:\n", |
| 35 | + " yield x\n", |
| 36 | + " x += 1" |
| 37 | + ] |
| 38 | + }, |
| 39 | + { |
| 40 | + "cell_type": "markdown", |
| 41 | + "metadata": {}, |
| 42 | + "source": [ |
| 43 | + "### Using the generator with a for loop\n", |
| 44 | + "Here, gene is a my_generator function. \n", |
| 45 | + "The for loop iterates through gene indefinitely. \n", |
| 46 | + "Behind the scenes, the for loop is calling the generator's \\__next__ function. \n", |
| 47 | + "Big advantages over Lists: \n", |
| 48 | + "- Generator can provide an infinite seqence. \n", |
| 49 | + "- Generator doesn't load values into memory. " |
| 50 | + ] |
| 51 | + }, |
| 52 | + { |
| 53 | + "cell_type": "code", |
| 54 | + "execution_count": 29, |
| 55 | + "metadata": {}, |
| 56 | + "outputs": [ |
| 57 | + { |
| 58 | + "name": "stdout", |
| 59 | + "output_type": "stream", |
| 60 | + "text": [ |
| 61 | + "<class 'generator'>\n", |
| 62 | + "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 " |
| 63 | + ] |
| 64 | + }, |
| 65 | + { |
| 66 | + "ename": "KeyboardInterrupt", |
| 67 | + "evalue": "", |
| 68 | + "output_type": "error", |
| 69 | + "traceback": [ |
| 70 | + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
| 71 | + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", |
| 72 | + "\u001b[0;32m<ipython-input-29-56f958421e1a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mgene\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m' '\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0.5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", |
| 73 | + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " |
| 74 | + ] |
| 75 | + } |
| 76 | + ], |
| 77 | + "source": [ |
| 78 | + "import time\n", |
| 79 | + "gene = my_generator()\n", |
| 80 | + "print(type(gene))\n", |
| 81 | + "\n", |
| 82 | + "for i in gene:\n", |
| 83 | + " print(i, end=' ')\n", |
| 84 | + " time.sleep(0.5)" |
| 85 | + ] |
| 86 | + }, |
| 87 | + { |
| 88 | + "cell_type": "markdown", |
| 89 | + "metadata": {}, |
| 90 | + "source": [ |
| 91 | + "### Using the generator with explicit next( ) calls\n", |
| 92 | + "*range* limits this for loop to 10 iterations. \n", |
| 93 | + "Each iteration of the for loop it calls the generator using *next(gene)*." |
| 94 | + ] |
| 95 | + }, |
| 96 | + { |
| 97 | + "cell_type": "code", |
| 98 | + "execution_count": 30, |
| 99 | + "metadata": {}, |
| 100 | + "outputs": [ |
| 101 | + { |
| 102 | + "name": "stdout", |
| 103 | + "output_type": "stream", |
| 104 | + "text": [ |
| 105 | + "1\n", |
| 106 | + "2 3 4 5 6 7 8 9 10 11 " |
| 107 | + ] |
| 108 | + } |
| 109 | + ], |
| 110 | + "source": [ |
| 111 | + "gene = my_generator()\n", |
| 112 | + "print(gene.__next__())\n", |
| 113 | + "for i in range(10):\n", |
| 114 | + " print(next(gene), end=' ')" |
| 115 | + ] |
| 116 | + }, |
| 117 | + { |
| 118 | + "cell_type": "markdown", |
| 119 | + "metadata": {}, |
| 120 | + "source": [ |
| 121 | + "### Generators from Generator Expressions\n", |
| 122 | + "Similar to List Comprehensions, but uses ( ) rather than [ ]. \n", |
| 123 | + "Create with a single line of code. \n", |
| 124 | + "Only use 120 bytes of memory." |
| 125 | + ] |
| 126 | + }, |
| 127 | + { |
| 128 | + "cell_type": "code", |
| 129 | + "execution_count": 31, |
| 130 | + "metadata": {}, |
| 131 | + "outputs": [ |
| 132 | + { |
| 133 | + "name": "stdout", |
| 134 | + "output_type": "stream", |
| 135 | + "text": [ |
| 136 | + "120\n", |
| 137 | + "<class 'generator'>\n", |
| 138 | + "0\n", |
| 139 | + "3\n" |
| 140 | + ] |
| 141 | + } |
| 142 | + ], |
| 143 | + "source": [ |
| 144 | + "gene = (x for x in range(999999))\n", |
| 145 | + "\n", |
| 146 | + "import sys\n", |
| 147 | + "print(sys.getsizeof(gene))\n", |
| 148 | + "print(type(gene))\n", |
| 149 | + "\n", |
| 150 | + "print(next(gene))\n", |
| 151 | + "next(gene)\n", |
| 152 | + "next(gene)\n", |
| 153 | + "print(next(gene))" |
| 154 | + ] |
| 155 | + }, |
| 156 | + { |
| 157 | + "cell_type": "markdown", |
| 158 | + "metadata": {}, |
| 159 | + "source": [ |
| 160 | + "### Generator to Read File\n", |
| 161 | + "Saves memory, and avoids memory overflow for very large files, because it only *loads one line into memory at a time*." |
| 162 | + ] |
| 163 | + }, |
| 164 | + { |
| 165 | + "cell_type": "code", |
| 166 | + "execution_count": 32, |
| 167 | + "metadata": {}, |
| 168 | + "outputs": [ |
| 169 | + { |
| 170 | + "name": "stdout", |
| 171 | + "output_type": "stream", |
| 172 | + "text": [ |
| 173 | + "Rolling Stones\n", |
| 174 | + "\n", |
| 175 | + "Lady Gaga\n", |
| 176 | + "Jackson Browne\n", |
| 177 | + "Maroon 5\n", |
| 178 | + "Arijit Singh\n", |
| 179 | + "Elton John\n", |
| 180 | + "John Mayer\n" |
| 181 | + ] |
| 182 | + } |
| 183 | + ], |
| 184 | + "source": [ |
| 185 | + "def read_file(fn = 'bands.txt'):\n", |
| 186 | + " for line in open(fn):\n", |
| 187 | + " yield line\n", |
| 188 | + " \n", |
| 189 | + "band = read_file()\n", |
| 190 | + "print(next(band))\n", |
| 191 | + "for i in range(6):\n", |
| 192 | + " print(next(band), end='')" |
| 193 | + ] |
| 194 | + }, |
| 195 | + { |
| 196 | + "cell_type": "code", |
| 197 | + "execution_count": null, |
| 198 | + "metadata": {}, |
| 199 | + "outputs": [], |
| 200 | + "source": [] |
| 201 | + } |
| 202 | + ], |
| 203 | + "metadata": { |
| 204 | + "kernelspec": { |
| 205 | + "display_name": "Python 3", |
| 206 | + "language": "python", |
| 207 | + "name": "python3" |
| 208 | + }, |
| 209 | + "language_info": { |
| 210 | + "codemirror_mode": { |
| 211 | + "name": "ipython", |
| 212 | + "version": 3 |
| 213 | + }, |
| 214 | + "file_extension": ".py", |
| 215 | + "mimetype": "text/x-python", |
| 216 | + "name": "python", |
| 217 | + "nbconvert_exporter": "python", |
| 218 | + "pygments_lexer": "ipython3", |
| 219 | + "version": "3.7.0" |
| 220 | + } |
| 221 | + }, |
| 222 | + "nbformat": 4, |
| 223 | + "nbformat_minor": 2 |
| 224 | +} |
0 commit comments