{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "

# Generators Comprehension Iterators

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Generators" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from random import randrange\n", "\n", "def randomly_generate_random_nonmultiples_of_ten_between_0_and_99():\n", " while True:\n", " digit = randrange(0, 100)\n", " if digit % 10:\n", " yield digit\n", " else:\n", " return\n", "\n", "generator = randomly_generate_random_nonmultiples_of_ten_between_0_and_99()\n", "while True:\n", " try:\n", " # Alternative: print(generator.__next__())\n", " print(next(generator))\n", " except StopIteration:\n", " print('A multiple of 10 was generated, which ended the process')\n", " break" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def generate_multiples_of(n):\n", " for i in range(1, 10):\n", " yield n * i\n", " \n", "def generate_multiples():\n", " for n in range(1, 10):\n", " yield from generate_multiples_of(n)\n", "\n", "count = 0\n", "generator = generate_multiples()\n", "for e in generator:\n", " print('{:3d}'.format(e), end = '')\n", " count += 1\n", " if count % 9 == 0:\n", " print()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from random import randint\n", "\n", "def randomly_announce_even_or_odd():\n", " while True:\n", " if randint(0, 1):\n", " print('It is odd.')\n", " else:\n", " print('It is even.')\n", " yield\n", "\n", "generator = randomly_announce_even_or_odd()\n", "for i in range(10):\n", " next(generator)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def yield_and_send():\n", " sent = None\n", " i = 0\n", " while True:\n", " if sent == None:\n", " # \"i\" is generated.\n", " # - If that follows a call to \"__next__()\",\n", " # \"sent\" then receives the value None.\n", " # - If that follows a call to \"send()\",\n", " # \"sent\" then receives the value passed as an argument to \"send()\".\n", " sent = yield i\n", " elif sent == 'stop':\n", " return\n", " else:\n", " # Same as above, except that it is \"sent + i\" that is generated.\n", " sent = yield sent + i\n", " i += 1\n", "\n", "generator = yield_and_send()\n", "# First \"next()\" has to be issued, \"send()\" cannot be issued.\n", "print(next(generator))\n", "# Now either \"next()\" or \"send()\" can be issued:\n", "# \"yield i\" has last been executed; \n", "# which of \"__next__()\" or \"send()\" will be called\n", "# will determine the value that \"sent\" will receive.\n", "print(next(generator))\n", "print(next(generator))\n", "print(generator.send(10))\n", "print(generator.send(20))\n", "print(next(generator))\n", "print(generator.send(30))\n", "print(next(generator))\n", "print(next(generator))\n", "try:\n", " print(generator.send('stop'))\n", "except StopIteration:\n", " print('Generation has been stopped')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Comprehension and generator expressions" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# More generally, any iterable.\n", "L = [0, 3, 2, 5, 1]\n", "\n", "# List comprehension\n", "print([i * i for i in L])\n", "print([i * i for i in L if i % 2])\n", "print()\n", "# Set comprehension\n", "print({i * i for i in L})\n", "print({i * i for i in L if i % 2})\n", "print()\n", "# Dictionnary comprehension\n", "print({i: i * i for i in L})\n", "print({i: i * i for i in L if i % 2})\n", "print()\n", "\n", "# \"print((i: i * i for i in L))\" and \"print((i: i * i for i in L if i % 2)\" are invalid:\n", "# there is no tuple comprehension.\n", "# \"(i: i * i for i in L)\" and \"(i: i * i for i in L if i % 2)\" are generator expressions:\n", "# the call to \"tuple()\" in \"tuple((i: i * i for i in L))\",\n", "# the call to \"tuple()\" in \"tuple((i: i * i for i in L if i % 2))\"\n", "# force the generator to produce all values;\n", "# the inner parentheses (for \"generator expression\") can be omitted.\n", "print(tuple(i * i for i in L))\n", "print(tuple(i * i for i in L if i % 2))\n", "print()\n", "for e in (i * i for i in L):\n", " print(e, end = ' ')\n", "print()\n", "for e in (i * i for i in L if i % 2):\n", " print(e, end = ' ')\n", "print('\\n')\n", "\n", "# List, set and dictionnary comprehension can be achieved with a similar technique:\n", "print(list(i * i for i in L))\n", "print(list(i * i for i in L if i % 2))\n", "print(set(i * i for i in L))\n", "print(set(i * i for i in L if i % 2))\n", "print(dict((i, i * i) for i in L))\n", "print(dict((i, i * i) for i in L if i % 2))\n", "print()\n", "# The parentheses for \"generator expression\" can be ommitted here too:\n", "print(sorted(i * i for i in L))\n", "# But they cannot be ommitted here:\n", "print(sorted((i * i for i in L), reverse = True))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "M = [[[111, 112, 113],\n", " [121, 122, 123],\n", " [131, 132, 133]],\n", " [[211, 212, 213],\n", " [221, 222, 223],\n", " [231, 232, 233]]]\n", "\n", "print([ 2 * element\n", " for three_rows in M\n", " for row in three_rows\n", " for element in row])\n", "print([ [ [ 2 * element\n", " for element in row]\n", " for row in three_rows]\n", " for three_rows in M])\n", "print()\n", "print([ 2 * element\n", " for three_rows in M\n", " if three_rows // 100 % 2\n", " for row in three_rows\n", " if row // 10 % 2\n", " for element in row\n", " if element % 2])\n", "print([ [ [ 2 * element\n", " for element in row \n", " if element % 2]\n", " for row in three_rows \n", " if row // 10 % 2]\n", " for three_rows in M \n", " if three_rows // 100 % 2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Iterators" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# More generally, any iterable.\n", "R = range(5)\n", "\n", "iterator_1 = iter(R)\n", "print(iterator_1 is R)\n", "print(next(iterator_1))\n", "print(next(iterator_1))\n", "iterator_2 = iter(R)\n", "print(iterator_2 is iterator_1)\n", "print(next(iterator_2))\n", "print(next(iterator_1))\n", "print(next(iterator_2))\n", "print()\n", "\n", "generator_expression = (e for e in R)\n", "\n", "iterator_1 = iter(generator_expression)\n", "print(iterator_1 is generator_expression)\n", "print(next(iterator_1))\n", "print(next(iterator_1))\n", "iterator_2 = iter(generator_expression)\n", "print(iterator_2 is iterator_1)\n", "print(next(iterator_2))\n", "print(next(iterator_1))\n", "print(next(iterator_2))\n", "print()\n", "\n", "def generate_R_members():\n", " for e in R:\n", " yield e\n", "\n", "generator = generate_R_members()\n", "iterator_1 = iter(generator)\n", "print(iterator_1 is generator)\n", "print(next(iterator_1))\n", "print(next(iterator_1))\n", "iterator_2 = iter(generator)\n", "print(iterator_2 is iterator_1)\n", "print(next(iterator_2))\n", "print(next(iterator_1))\n", "print(next(iterator_2))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.3" } }, "nbformat": 4, "nbformat_minor": 0 }