{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Generatorların Oluşturulması ve Kullanılması\n", "\n", "Bu derste Pythondaki generatorları anlamaya çalışacağız. \n", "\n", "Generatorlar Pythonda **iterable** objeler (örnek olarak fonksiyonlar) oluşturmak için kullanılan objelerdir ve bellekte herhangi bir yer kaplamazlar. Örneğin, 100.000 tane değer üretip, bu değerleri bir listede tutmak bellekte oldukça fazla yer kaplayacaktır. O yüzden bu işlemi gerçekleştiren bir fonksiyonu generator fonksiyon şeklinde yazmak oldukça mantıklı olacaktır. Generatorları anlamak için isterseniz bir fonksiyonu ilk olarak generator kullanmadan yazmaya çalışalım." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 4, 9, 16, 25]\n" ] } ], "source": [ "def karelerial():\n", " sonuç = []\n", " \n", " for i in range(1,6):\n", " sonuç.append(i**2)\n", " return sonuç\n", "\n", "\n", "print(karelerial())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "İsterseniz bu fonksiyonu bir de generator kullanarak yazmaya çalışalım. Generatorlerin değer üretmesi için **yield** anahtar kelimesini kullanacağız." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "def karelerial():\n", " for i in range(1,6):\n", " yield i ** 2 # yield anahtar kelimesi generator'un değer üretmesi için kullanılıyor.\n", "generator = karelerial()\n", "\n", "print(generator) # Generator objesi" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Yazdığımız ilk fonksiyonda 1'den 6'ya kadar gidip her bir değerin karesini **sonuç** isimli listeye atıyoruz ve daha sonra bu listeyi dönüyoruz.Yani bellekte liste değişkenin içinde 1,4,9,16,25 değerleri tutuluyor.\n", "\n", "Generatorle yazdığımız 2.fonksiyonda **yield** anahtar kelimesiyle değerleri ürettiğimizi sanıyoruz. Ama aslında bu fonksiyonu çağırınca bize sadece bir tane generator objesi dönüyor ve biz sadece generator objesinin değerlerine ulaşmaya çalıştığımızda değerler tek tek üretiliyor. Yani kısacası bellekte değerler tutulmuyor. Bu generator objesinin üzerinde bir tane iterator oluşturarak durumu daha iyi anlamaya çalışalım." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "4\n", "9\n", "16\n", "25\n" ] }, { "ename": "StopIteration", "evalue": "", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mStopIteration\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0miterator\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0miterator\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 8\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0miterator\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mStopIteration\u001b[0m: " ] } ], "source": [ "iterator = iter(generator)\n", "\n", "print(next(iterator)) # 1 değeri üretildi\n", "print(next(iterator)) # 4 değeri üretildi 1 değeri tarihe karıştı.\n", "print(next(iterator)) # 9 değeri üretildi 4 değeri tarihe karıştı.\n", "print(next(iterator)) # 16 değeri üretildi 9 değeri tarihe karıştı\n", "print(next(iterator)) # 25 değeri üretildi 16 değeri tarihe karıştı.\n", "print(next(iterator)) # Üretilecek değer kalmadı." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aslında generator objesi sadece değerlere ulaşmak istediğimiz zaman **yield** anahtar kelimesini kullanıp değer üretiyor. Yani generatorler sadece biz değerlere ulaşmak istersek çalışıyor. İşte generatorlerin mantığı tamamıyla bu şekilde ! Şimdi de list comprehensionları generatorlara çevirmeye çalışalım." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "liste = [i * 3 for i in range(5)]" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 3, 6, 9, 12]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "liste" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Böyle bir list comprehension'ı generator objesine çevirmek için [] yerine () kullanıyoruz." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": true }, "outputs": [], "source": [ "generator = (i * 3 for i in range(5))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " at 0x0000009441374990>\n" ] } ], "source": [ "print(generator)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": true }, "outputs": [], "source": [ "iterator = iter(generator)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n" ] } ], "source": [ "print(next(iterator))" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n" ] } ], "source": [ "print(next(iterator))" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6\n" ] } ], "source": [ "print(next(iterator))" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9\n" ] } ], "source": [ "print(next(iterator))" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "12\n" ] } ], "source": [ "print(next(iterator))" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "ename": "StopIteration", "evalue": "", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mStopIteration\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0miterator\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mStopIteration\u001b[0m: " ] } ], "source": [ "print(next(iterator))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "İsterseniz konuyu anlamak için bir tane daha generator fonksiyonu oluşturalım.\n" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def carpimtablosu():\n", " for i in range(1,11):\n", " for j in range(1,11):\n", " yield \"{} x {} = {}\".format(i,j,i*j)\n" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 x 1 = 1\n", "1 x 2 = 2\n", "1 x 3 = 3\n", "1 x 4 = 4\n", "1 x 5 = 5\n", "1 x 6 = 6\n", "1 x 7 = 7\n", "1 x 8 = 8\n", "1 x 9 = 9\n", "1 x 10 = 10\n", "2 x 1 = 2\n", "2 x 2 = 4\n", "2 x 3 = 6\n", "2 x 4 = 8\n", "2 x 5 = 10\n", "2 x 6 = 12\n", "2 x 7 = 14\n", "2 x 8 = 16\n", "2 x 9 = 18\n", "2 x 10 = 20\n", "3 x 1 = 3\n", "3 x 2 = 6\n", "3 x 3 = 9\n", "3 x 4 = 12\n", "3 x 5 = 15\n", "3 x 6 = 18\n", "3 x 7 = 21\n", "3 x 8 = 24\n", "3 x 9 = 27\n", "3 x 10 = 30\n", "4 x 1 = 4\n", "4 x 2 = 8\n", "4 x 3 = 12\n", "4 x 4 = 16\n", "4 x 5 = 20\n", "4 x 6 = 24\n", "4 x 7 = 28\n", "4 x 8 = 32\n", "4 x 9 = 36\n", "4 x 10 = 40\n", "5 x 1 = 5\n", "5 x 2 = 10\n", "5 x 3 = 15\n", "5 x 4 = 20\n", "5 x 5 = 25\n", "5 x 6 = 30\n", "5 x 7 = 35\n", "5 x 8 = 40\n", "5 x 9 = 45\n", "5 x 10 = 50\n", "6 x 1 = 6\n", "6 x 2 = 12\n", "6 x 3 = 18\n", "6 x 4 = 24\n", "6 x 5 = 30\n", "6 x 6 = 36\n", "6 x 7 = 42\n", "6 x 8 = 48\n", "6 x 9 = 54\n", "6 x 10 = 60\n", "7 x 1 = 7\n", "7 x 2 = 14\n", "7 x 3 = 21\n", "7 x 4 = 28\n", "7 x 5 = 35\n", "7 x 6 = 42\n", "7 x 7 = 49\n", "7 x 8 = 56\n", "7 x 9 = 63\n", "7 x 10 = 70\n", "8 x 1 = 8\n", "8 x 2 = 16\n", "8 x 3 = 24\n", "8 x 4 = 32\n", "8 x 5 = 40\n", "8 x 6 = 48\n", "8 x 7 = 56\n", "8 x 8 = 64\n", "8 x 9 = 72\n", "8 x 10 = 80\n", "9 x 1 = 9\n", "9 x 2 = 18\n", "9 x 3 = 27\n", "9 x 4 = 36\n", "9 x 5 = 45\n", "9 x 6 = 54\n", "9 x 7 = 63\n", "9 x 8 = 72\n", "9 x 9 = 81\n", "9 x 10 = 90\n", "10 x 1 = 10\n", "10 x 2 = 20\n", "10 x 3 = 30\n", "10 x 4 = 40\n", "10 x 5 = 50\n", "10 x 6 = 60\n", "10 x 7 = 70\n", "10 x 8 = 80\n", "10 x 9 = 90\n", "10 x 10 = 100\n" ] } ], "source": [ "for i in carpimtablosu():\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Buradaki bu kadar işlemi listelerde tutmak o kadar mantıklı değil. Onun yerine bellekte yer kaplamayan ve sadece her ulaşmaya çalıştığımızda değer üreten(**yield**) generator fonksiyonları kullanmak daha mantıklı olacaktır. \n", "\n", "\n", "Peki generatorlar Pythonda nerede kullanılıyor ? Aslında bizim daha önce öğrendiğimiz **range** fonksiyonu Pythonda generatorlar yazılmış bir fonksiyondur. \n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n", "10\n", "11\n", "12\n", "13\n", "14\n", "15\n", "16\n", "17\n", "18\n", "19\n", "20\n", "21\n", "22\n", "23\n", "24\n", "25\n", "26\n", "27\n", "28\n", "29\n", "30\n", "31\n", "32\n", "33\n", "34\n", "35\n", "36\n", "37\n", "38\n", "39\n", "40\n", "41\n", "42\n", "43\n", "44\n", "45\n", "46\n", "47\n", "48\n", "49\n", "50\n", "51\n", "52\n", "53\n", "54\n", "55\n", "56\n", "57\n", "58\n", "59\n", "60\n", "61\n", "62\n", "63\n", "64\n", "65\n", "66\n", "67\n", "68\n", "69\n", "70\n", "71\n", "72\n", "73\n", "74\n", "75\n", "76\n", "77\n", "78\n", "79\n", "80\n", "81\n", "82\n", "83\n", "84\n", "85\n", "86\n", "87\n", "88\n", "89\n", "90\n", "91\n", "92\n", "93\n", "94\n", "95\n", "96\n", "97\n", "98\n", "99\n" ] } ], "source": [ "for i in range(100): # Sadece istediğimiz zaman sayılara ulaşıyoruz.\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "İşte generatorların genel mantığı bu şekilde. Anlamadığınız bir yer olursa lütfen çekinmeden sorun. Bir sonraki derste görüşmek üzere." ] }, { "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 }