{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 32. 긴 리스트 컴프리헨션보다는 제너레이터 식을 사용하라"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "리스트 컴프리헨션을 사용할 경우 입력이 커지면 메모리를 상당히 많이 사용한다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5, 4, 9, 17, 9, 11, 8, 9, 11, 8, 5]\n"
     ]
    }
   ],
   "source": [
    "value = [len(x) for x in open('my_file.txt')]\n",
    "print(value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "제너레이터 식은 리스트 컴프리헨션과 제너레이터를 일반화한 것이다.\n",
    "\n",
    "제너레이터 식을 실행해도 출력 시퀀스 전체가 실체화되지는 않는다.\n",
    "\n",
    "그대신 제너레이터 식에 들어 있는 식으로부터 원소를 하나씩 만들어내는 이터레이터가 생성된다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<generator object <genexpr> at 0x7f86f8c8cc10>\n"
     ]
    }
   ],
   "source": [
    "it = (len(x) for x in open('my_file.txt'))\n",
    "print(it)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "print(next(it))\n",
    "print(next(it))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "메모리를 모두 소모하는 것을 막을 수 있음\n",
    "\n",
    "제너레이터 식의 또 다른 강력한 특징은 두 제너레이터 식을 합성할 수 있다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "roots = ((x, x**0.5) for x in it)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(9, 3.0)\n"
     ]
    }
   ],
   "source": [
    "print(next(roots))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(17, 4.123105625617661)\n"
     ]
    }
   ],
   "source": [
    "print(next(roots))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "이처럼 제너레이터를 함께 연결한 코드를 파이썬은 아주 빠르게 실행할 수 있다.\n",
    "\n",
    "아주 큰 입력 스트림에 대해 여러 기능을 합성해 적용해야 한다면, 제너레이터 식을 선택하라.\n",
    "\n",
    "다만 이터레이터이므로 한번만 사용해야 한다."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 기억해야 할 내용\n",
    "- 입력이 크면 메모리를 너무 많이 사용하기 때문에 리스트 컴프리헨션은 문제를 일으킬 수 있다.\n",
    "- 제너레이터 식은 이터레이터처럼 한 번에 원소를 하나씩 출력하기 때문에 메모리 문제를 피할 수 있다.\n",
    "- 제너레이터 식이 반환한 이터레이터를 다른 제너레이터 식의 하위 식으로 사용함으로써 제너레이터 식을 서로 합성할 수 있다.\n",
    "- 서로 연결된 제너레이터 식은 매우 빠르게 실행되며 메모리도 효율적으로 사용한다."
   ]
  }
 ],
 "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.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}