542 lines
11 KiB
Plaintext
542 lines
11 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2663b868-8c7e-4776-9c3b-0cc03d581ee5",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Generators & Comprehensions\n",
|
|
"\n",
|
|
"### Generator Functions\n",
|
|
"\n",
|
|
"A generator function works differently from all of the functions we've seen before. It allows the function to return (using the `yield` statement) and resume where it left off, with internal state intact.\n",
|
|
"\n",
|
|
"Between calls to the generator function, state is suspended."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "f6f883d1-88fd-4488-8af7-17c15a47e933",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def simple_generator_func():\n",
|
|
" print(\"start\")\n",
|
|
" yield 1\n",
|
|
" print(\"still running\")\n",
|
|
" yield 2\n",
|
|
" print(\"one more\")\n",
|
|
" yield 3"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "2260b250-1ae6-4d3b-ab05-314ddad19256",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<generator object simple_generator_func at 0x1064afd80>"
|
|
]
|
|
},
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# return type of a yielding function is a generator\n",
|
|
"simple_generator_func()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "c051b45d-9a37-4086-b90c-2090110c8cc6",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"g = simple_generator_func()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "427fe881-459e-4a20-acfa-dae65a1b906c",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"source": [
|
|
"##"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "6a87d7d2-9eb5-4415-9770-79d9594aafa5",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"start\n",
|
|
"yielded value= 1\n",
|
|
"still running\n",
|
|
"yielded value= 2\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"for x in simple_generator_func():\n",
|
|
" print(\"yielded value=\", x)\n",
|
|
" if x == 2:\n",
|
|
" break"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "544d5a37-a1c0-47f6-b270-429ea2215386",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def evens_up_to(n): \n",
|
|
" for i in range(2, n + 1):\n",
|
|
" if i % 2 == 0:\n",
|
|
" yield i"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "7fbc6cf5-0995-4d20-b47d-6b5454899168",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2\n",
|
|
"4\n",
|
|
"6\n",
|
|
"8\n",
|
|
"10\n",
|
|
"12\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"for evens in evens_up_to(10000000000000):\n",
|
|
" print(evens)\n",
|
|
" if evens > 10:\n",
|
|
" break"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "2fbf706b-6f6c-4a24-890e-10121d709582",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Generators do not have to ever exit, here is an infinite generator\n",
|
|
"def powers_of_two():\n",
|
|
" n = 2\n",
|
|
" while True:\n",
|
|
" yield n\n",
|
|
" n *= 2"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "32920b91-7b00-4b2a-8927-07bd5cbc6fa2",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# list(powers_of_two())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "27a8bd75-3912-4f97-9655-763279f07f9b",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2\n",
|
|
"4\n",
|
|
"8\n",
|
|
"16\n",
|
|
"32\n",
|
|
"64\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"for x in powers_of_two():\n",
|
|
" if x > 100:\n",
|
|
" break\n",
|
|
" print(x)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "dd4f4d70-e74a-43d3-88bc-7dfe04add2a2",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"range(0, 1000000000000000000)"
|
|
]
|
|
},
|
|
"execution_count": 10,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"range(1000000000000000000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "9be584c1-4cf9-4ad3-88ab-4b5da18e42da",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"g = powers_of_two()\n",
|
|
"h = powers_of_two()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "81095f30-547f-4624-b2a4-9cc5997c4a8b",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"True"
|
|
]
|
|
},
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"g is not h"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"id": "e34470cd-efdd-45d0-a1b5-58e478260e4c",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"2"
|
|
]
|
|
},
|
|
"execution_count": 13,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"next(g)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "2e656696-8e3e-4dfd-86f9-9b87a08debe3",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"2"
|
|
]
|
|
},
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"next(h)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"id": "39b39657-243c-4641-9859-90fdb7adb3fc",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"range(0, 100)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"r = range(100)\n",
|
|
"print(r)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "308fc5a9-78ac-40cd-afac-970614e9460e",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Discussion: Benefits of Generators"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4fefa3b8-0727-4586-97df-698b91d91c6f",
|
|
"metadata": {},
|
|
"source": [
|
|
"- Avoids creating entire collections up front.\n",
|
|
"\n",
|
|
"- Can result in drastic memory savings.\n",
|
|
"\n",
|
|
" - How much memory does `range(100000)` need?\n",
|
|
"\n",
|
|
"- Avoids doing expensive computations until necessary."
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"id": "229fa10f-331e-4b72-959e-d28b952760ee",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Generator Expressions / Comprehensions\n",
|
|
"\n",
|
|
"Exact same syntax as a list comprehension, but results in a generator object.\n",
|
|
"\n",
|
|
"\n",
|
|
"```python\n",
|
|
"g = (expression for var in iterable)\n",
|
|
"\n",
|
|
"# or \n",
|
|
"\n",
|
|
"g = (expression for var in iterable if condition)\n",
|
|
"```\n",
|
|
"\n",
|
|
"Creates a generator that yields `expression` for each iteration of the for loop. (Optionally only if the `condition` is satisfied)\n",
|
|
"\n",
|
|
"Equivalent to:\n",
|
|
"\n",
|
|
"```python\n",
|
|
"def g():\n",
|
|
" for var in iterable:\n",
|
|
" if condition:\n",
|
|
" yield expression\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 37,
|
|
"id": "aa9b4c18-3d73-4d9c-8e78-3dba56b4a717",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"<generator object <genexpr> at 0x107f1cf90>\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"pow_generator = (i + 1 for i in powers_of_two())\n",
|
|
"print(pow_generator)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "2e69c9d6-11ec-4e01-9116-95f55c8c2c7e",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 38,
|
|
"id": "729f6476-491a-4daf-b460-23f602ef18fa",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"3\n",
|
|
"5\n",
|
|
"9\n",
|
|
"17\n",
|
|
"33\n",
|
|
"65\n",
|
|
"129\n",
|
|
"257\n",
|
|
"513\n",
|
|
"1025\n",
|
|
"2049\n",
|
|
"4097\n",
|
|
"8193\n",
|
|
"16385\n",
|
|
"32769\n",
|
|
"65537\n",
|
|
"131073\n",
|
|
"262145\n",
|
|
"524289\n",
|
|
"1048577\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# can be used just like other generators we've seen (as an iterable)\n",
|
|
"for i in pow_generator:\n",
|
|
" print(i)\n",
|
|
" # will run forever without this\n",
|
|
" if i > 1000000:\n",
|
|
" break"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 39,
|
|
"id": "cfed52c0-0467-4b50-ac6c-66d6fa694ec6",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2097153\n",
|
|
"4194305\n",
|
|
"8388609\n",
|
|
"16777217\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"for x in pow_generator:\n",
|
|
" print(x) # can resume the generator\n",
|
|
" if x > 10000000:\n",
|
|
" break"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 49,
|
|
"id": "ac1be105-edc6-4b52-8715-e54c186861d2",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"[0, 4, 16, 36, 64]"
|
|
]
|
|
},
|
|
"execution_count": 49,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# also possible to specify conditionals in generator expression, same as comprehension\n",
|
|
"gen2 = (i**2 for i in range(10) if i % 2 == 0)\n",
|
|
"list(gen2)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 52,
|
|
"id": "c721ff55-86ac-46b1-826f-4613905162c8",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"[0, 4, 16, 36, 64]"
|
|
]
|
|
},
|
|
"execution_count": 52,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# equivalent with map & filter\n",
|
|
"ll = range(10)\n",
|
|
"list(map(lambda x: x**2, filter(lambda x: x % 2 == 0, ll)))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a5aba588-3823-4763-b1ab-5a6217f72f8e",
|
|
"metadata": {
|
|
"tags": []
|
|
},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"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.10.15"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|