{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "ca5ff68d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<generator object <genexpr> at 0x7f64fdcc4d60>\n",
      "<class 'generator'>\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "Python has a for-expression that returns a generator:\n",
    "\n",
    "    (<expression> for i in s if <conditional>)\n",
    "    \n",
    "is equivalent to:\n",
    "\n",
    "    for i in s:\n",
    "        if condition:\n",
    "            yield expression\n",
    "\n",
    "\"\"\"\n",
    "\n",
    "a = [1,2,3,4]\n",
    "b = (2*x for x in a)      # Returns a GENERATOR object !!!\n",
    "\n",
    "print(b)\n",
    "print(type(b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "bdfaeaab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "4\n",
      "6\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "# Therefore:\n",
    "\n",
    "for x in b:\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "6098e4f8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 4, 6, 8]\n",
      "<class 'list'>\n",
      "\n",
      "Done\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "Difference between generator expression and list comprehenson:\n",
    "\n",
    "    (1) Does not construct a list.\n",
    "    (2) Only useful purpose is iteration.\n",
    "    (3) Once consumed, can’t be reused.\n",
    "\n",
    "\"\"\"\n",
    "\n",
    "# List comprehension:\n",
    "a = [1,2,3,4]\n",
    "newlist_a = [2*x for x in a]        # Constructs a LIST\n",
    "    \n",
    "print(newlist_a)\n",
    "print(type(newlist_a))   \n",
    "\n",
    "print()\n",
    "# Once an iterator is consumed, it's empty:\n",
    "for x in b:\n",
    "    print(x)\n",
    "print(\"Done\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b62310a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "The main use of generator expressions is in code that performs some calculation on a sequence, \n",
    "but only uses the result ONCE. \n",
    "\"\"\"\n",
    "\n",
    "# For example, strip all comments from a file:\n",
    "\n",
    "f = open('somefile.txt')\n",
    "\n",
    "lines = (line for line in f if not line.startswith('#')) # Create a generator object\n",
    "                                                         # that strips comment lines\n",
    "\n",
    "for line in lines:\n",
    "    ...\n",
    "f.close()\n",
    "\n",
    "\"\"\"\n",
    "Advantage of generators over list comprehension:\n",
    "\n",
    "    With generators, the code runs faster and uses little memory. \n",
    "    \n",
    "It’s like a filter applied to a stream.\n",
    "\n",
    "Why Generators\n",
    "\n",
    "    Many problems are much more clearly expressed in terms of iteration.\n",
    "        Looping over a collection of items and performing some kind of operation \n",
    "        (searching, replacing, modifying, etc.).\n",
    "        Processing pipelines can be applied to a wide range of data processing problems.\n",
    "        \n",
    "    Better memory efficiency.\n",
    "        Only produce values when needed.\n",
    "        Contrast to constructing giant lists.\n",
    "        Can operate on streaming data\n",
    "        \n",
    "    Generators encourage code reuse\n",
    "        Separates the iteration from code that uses the iteration\n",
    "        You can build a toolbox of interesting iteration functions and mix-n-match.\n",
    "\"\"\""
   ]
  }
 ],
 "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.8.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
