{ "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 }