{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# generator, yield, iterable, iterator" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### generator\n", "- A function which returns an iterator. It looks like a normal function except that it contains yield statements for producing a series of values usable in a for-loop or that can be retrieved one at a time with the next() function. Each yield temporarily suspends processing, remembering the location execution state (including local variables and pending try-statements). When the generator resumes, it picks-up where it left-off (in contrast to functions which start fresh on every invocation).\n", "\n", "- iterator한 요소를 return하는 함수\n", "- yield란 키워드를 사용하며, next()란 함수로 다음 값을 나타낼 수 있음\n", "- 일반적인 함수는 사용이 종료되면 결과값을 호출부로 반환한 후, 함수 자체를 종료시키고 메모리상에서 clear\n", "\n", "\n", "- generator 함수가 실행 중 yield가 존재하면, 해당 함수는 그 상태로 정지되고 반환 값을 next() 호출한 쪽으로 전달. => local 변수나 instruction pointer 등과 같이 함수 내부에서 사용된 데이터들이 메모리에 그대로 유지됨\n", "\n", "- 메모리를 효율적으로 관리할 수 있어, 대용량 처리 함수를 제작할 때 용이함\n", "- list comprehension 형태에서 [] 대신 ()을 사용하면 generator가 생성됨" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ " at 0x110529780>" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(i for i in range(1000) if i % 2)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import sys" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4272" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sys.getsizeof( [i for i in range(1000) if i % 2] )\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "88" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sys.getsizeof( (i for i in range(1000) if i % 2) )\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def generator(n):\n", " i = 0\n", " while i < n:\n", " yield i\n", " i += 1\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### iterable\n", "\n", "- list, str, and tuple) and some non-sequence types like dict and file and objects of any classes you define with an __iter__() or __getitem__() method. Iterables can be used in a for loop and in many other places where a sequence is needed (zip(), map(), ...). When an iterable object is passed as an argument to the built-in function iter(), it returns an iterator for the object. This iterator is good for one pass over the set of values. When using iterables, it is usually not necessary to call iter() or deal with iterator objects yourself. The for statement does that automatically for you, creating a temporary unnamed variable to hold the iterator for the duration of the loop. See also iterator, sequence, and generator.\n", "\n", "- list, str, tuple 같이 순회할 수 있는 객체\n", "- __iter__() 나 __getitem__() 메소드로 정의된 class 는 모두 iterable \n", "\n", "\n", "### iterate\n", "- An object representing a stream of data. Repeated calls to the iterator’s next() method return successive items in the stream. When no more data are available a StopIteration exception is raised instead. At this point, the iterator object is exhausted and any further calls to its next() method just raise StopIteration again. Iterators are required to have an __iter__() method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted. One notable exception is code which attempts multiple iteration passes. A container object (such as a list) produces a fresh new iterator each time you pass it to the iter() function or use it in a for loop. Attempting this with an iterator will just return the same exhausted iterator object used in the previous iteration pass, making it appear like an empty container.\n", "\n", "- next() 메소드로 데이터를 순차적으로 호출 가능한 object \n", "\n", "\n", "- iterable 이라고 해서 반드시 iterator 라는 것은 아님\n", "- iter()를 사용하면 iterable한 객체를 iterator로 만들 수 있음\n", "- list나 tuple을 for문 돌리는 경우엔 iter를 정의하지 않아도 순차적으로 접근이 가능한 것은 python 내부에서 list를 임시적으로 iterator로 변환해줬기 때문-!" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = [1,2,3]" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "ename": "AttributeError", "evalue": "'list' object has no attribute 'next'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m: 'list' object has no attribute 'next'" ] } ], "source": [ "x.next()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "list" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(x)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "y = iter(x)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "list_iterator" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(y)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(y)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(y)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(y)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "ename": "StopIteration", "evalue": "", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mStopIteration\u001b[0m: " ] } ], "source": [ "next(y)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "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.6.1" } }, "nbformat": 4, "nbformat_minor": 2 }