{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "# Függvényhívás\n", "Mi történik függvényhíváskor? Pl:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def negyzetel(L):\n", " uj_L = []\n", " for i in L:\n", " uj_L.append(i*i)\n", " return uj_L\n", "\n", "szamok = [5, 1, 8]\n", "negyzetelt_szamok = negyzetel(szamok)\n", "\n", "print szamok\n", "print negyzetelt_szamok" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Itt egyszerűen az [5, 1, 8] lista elemeit emeljük négyzetre. Mi történik, ha közvetlenül a paraméterként kapott L lista elemeit emeljük négyzetre?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def negyzetel(L):\n", " for i in range(len(L)):\n", " L[i] = L[i] * L[i]\n", " return L\n", "\n", "szamok = [5, 1, 8]\n", "negyzetelt_szamok = negyzetel(szamok)\n", "\n", "print szamok\n", "print negyzetelt_szamok" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Mitől változott meg így az argumentumként átadott szamok lista is? Nézzünk mégegy példát:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def negyzetel(n):\n", " n = n * n\n", " return n\n", "\n", "szam = 5\n", "negyzetelt_szam = negyzetel(szam)\n", "\n", "print szam\n", "print negyzetelt_szam" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Most miért nem változott meg az argumentumként adott szam, mikor a függvényben megváltoztattuk a paraméter értékét?" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Érték szerinti paraméterátadás\n", "Pythonban és sok más programnyelvben egy függvény paraméterei érték szerint adódnak át.\n", "\n", "Ez azt jelenti, hogy egy függvény paraméterei nem egyeznek meg az argumentumként adott változókkal, hanem azok másolatai lesznek. Ezért nem változott meg az előző példában a szam változó.\n", "\n", "A listák esetében is másolat adódik át, de a másolat nem a listáról készül, hanem a lista memóriacíméről.\n", "\n", "Összetett adatszerkezetek változói, mint a lista valójában egy memóriacímet tárolnak, azt a címet ahol a lista található a számítógép memóriájában.\n", "\n", "1. példa\n", "\n", "2. példa\n", "\n", "3. példa\n", "\n", "Mégegy példa\n", "\n", "Ezért amikor olyan függvényt írunk mely listát kap paraméterként, mindig érdemes előre tisztázni, hogy a függvény megváltoztatja-e a lista elemeit vagy nem." ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Listák másolása (kitérő)\n", "\n", "Ha listát elemenként akarunk másolni, akkor azt nem tehetjük egy egyenlőségjellel. Pl. mi a helyzet a tömbbel (listák listájával)?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "M1 = [[1, 2], [3, 4]]\n", "M2 = M1[:]\n", "\n", "M2[0][0] = 5\n", "\n", "print M1\n", "print M2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "M1 = [[1, 2], [3, 4]]\n", "M2 = M1[:]\n", "\n", "M2[0] = [5, 2]\n", "\n", "print M1\n", "print M2" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Mi is történik most?\n", "\n", "1. példa\n", "\n", "2. példa\n", "\n", "Látható, a részlistás másolással az külső lista lemásolódott, de a belsők még mindig ugyanazok.\n", "\n", "Hogyan másoljunk biztosan akármilyen mélységig listát:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "import copy\n", "\n", "M1 = [[1, 2], [3, 4]]\n", "M2 = copy.deepcopy(M1)\n", "\n", "M2[0][0] = 5\n", "\n", "print M1\n", "print M2" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "A copy csomag a másolásra hasznos függvényeket tartalmazza, a deepcopy függvény jól lemásol egy listát, akármilyen mély legyen.\n", "\n", "## Opcionális függvény paraméter\n", "\n", "Megtörténhet, hogy egy függvénynek nem mindig akarjuk megadni az egyik paraméterét, mert pl. legtöbbször ugyanazzal az értékkel használnánk:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def atmentek(hallgatok, ponthatar):\n", " atment = []\n", " for hallgato in hallgatok:\n", " if hallgatok[hallgato] >= ponthatar:\n", " atment.append(hallgato)\n", " return atment\n", "\n", "hallgatok = {'RABCA8': 50, 'TCD1FG': 23, 'BB87FG': 67}\n", "print atmentek(hallgatok, 40)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Ekkor csinálhatjuk a következőt:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def atmentek(hallgatok, ponthatar = 40):\n", " atment = []\n", " for hallgato in hallgatok:\n", " if hallgatok[hallgato] >= ponthatar:\n", " atment.append(hallgato)\n", " return atment\n", "\n", "hallgatok = {'RABCA8': 50, 'TCD1FG': 23, 'BB87FG': 67}\n", "print atmentek(hallgatok)\n", "print atmentek(hallgatok, 60)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Nem csak egy opcionális paraméter adható meg, de az opcionális paraméterek csak jobbról adódhatnak:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def atmentek(hallgatok, ponthatar = 40, sorban = True):\n", " atment = []\n", " for hallgato in hallgatok:\n", " if hallgatok[hallgato] >= ponthatar:\n", " atment.append(hallgato)\n", " if sorban:\n", " return sorted(atment)\n", " else:\n", " return atment\n", "\n", "hallgatok = {'RABCA8': 50, 'TCD1FG': 23, 'XB87FG': 67}\n", "print atmentek(hallgatok)\n", "print atmentek(hallgatok, 40, False)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "A következő hibás, mert a ponthatárt állítjuk False-ra:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "print atmentek(hallgatok, False)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Ilyet lehet, de kicsit kényelmetlen:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "print atmentek(hallgatok, sorban = False)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "# Referenciák, objektumok típusa\n", "\n", "Az olyan dolgokat, melyekre a memóriában található helyükre hivatkozunk (pl: lista, szótár) objektumoknak nevezzük. Később megismerünk többféle objektumot.\n", "\n", "Az objektumoknak van egy típusa, más szóval osztálya, ami megmondja, hogy az adott objektum épp egy lista, vagy szótár vagy stb. Az objektum osztályától függ, hogy milyen metódusokat lehet rajta meghívni, például listának van sort metódusa, de szótárnak nincs.\n", "\n", "A változók, melyek egy adott objektumra hivatkoznak azok referenciák az objektumra és úgy mondjuk, hogy erre az objektumra mutatnak." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true, "deletable": true, "editable": true }, "outputs": [], "source": [ "L1 = [1, 2, 5]\n", "L2 = L1" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Ebben a példában L1 és L2 is ugyanarra az objektumra, egy listára mutat." ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Függvény referencia\n", "\n", "Ha már ismerjük a referencia fogalmát, akkor egyszerűen adódik, hogy a függvények is csak referenciák, így használhatók akár függvény argumentumként is. Emlékezzünk előbb vissza a buborék rendezés algoritmusra:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def rendez(lista):\n", " rendezett = lista[:]\n", " for i in range(len(lista) - 1):\n", " for j in range(len(lista) - i - 1):\n", " if rendezett[j] > rendezett[j + 1]:\n", " temp = rendezett[j]\n", " rendezett[j] = rendezett[j + 1]\n", " rendezett[j + 1] = temp\n", " return rendezett\n", "\n", "L = [1, 8, 5, 2, 9, 3, 6]\n", "\n", "print rendez(L)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Módosítsuk ezt úgy, hogy bármilyen rendezésre működjön:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def rendez(lista, hasonlit):\n", " rendezett = lista[:]\n", " for i in range(len(lista) - 1):\n", " for j in range(len(lista) - i - 1):\n", " if hasonlit(rendezett[j], rendezett[j + 1]):\n", " temp = rendezett[j]\n", " rendezett[j] = rendezett[j + 1]\n", " rendezett[j + 1] = temp\n", " return rendezett\n", "\n", "def novekvo(a, b):\n", " if a < b:\n", " return False\n", " else:\n", " return True\n", " \n", "def csokkeno(a, b):\n", " if a > b:\n", " return False\n", " else:\n", " return True\n", " \n", "L = [1, 8, 5, 2, 9, 3, 6]\n", "\n", "print rendez(L, novekvo)\n", "print rendez(L, csokkeno)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Ha már itt tartunk, akkor kiegészíthetjük opcionális paraméterrel is:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def novekvo(a, b):\n", " if a < b:\n", " return False\n", " else:\n", " return True\n", " \n", "def csokkeno(a, b):\n", " if a > b:\n", " return False\n", " else:\n", " return True\n", "\n", "def rendez(lista, hasonlit = novekvo):\n", " rendezett = lista[:]\n", " for i in range(len(lista) - 1):\n", " for j in range(len(lista) - i - 1):\n", " if hasonlit(rendezett[j], rendezett[j + 1]):\n", " temp = rendezett[j]\n", " rendezett[j] = rendezett[j + 1]\n", " rendezett[j + 1] = temp\n", " return rendezett\n", "\n", "L = [1, 8, 5, 2, 9, 3, 6]\n", "\n", "print rendez(L)\n", "print rendez(L, csokkeno)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "# Listaértelmezés\n", "\n", "Bonyolult listák létrehozhatók gyorsan és többnyire átláthatóan listaértelmezéssel:\n", "\n", "[kifejezés for elem in bejárható_objektum]\n", "\n", "Pl:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "[x * x for x in range(10)]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Feltételekkel is ki lehet egészíteni a listaértelmezést:\n", "\n", "[kifejezés for elem in bejárható_objektum if feltetel]\n", "\n", "Pl:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "[x * x for x in range(10) if x % 2 == 1]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Akárhány for és if szerepelhet benne:\n", "\n", "[kifejezés for elem1 in bejárható_objektum1 if feltétel1\n", " for elem2 in bejárható_objektum2 if feltétel2\n", " ...\n", " for elemN in bejárható_objektumN if feltételN]\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "[x + y for x in range(4) for y in range(4)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "[[x + y for x in range(4)] for y in range(4)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "[n for n in range(1, 100) \n", " if n == sum([m for m in range(1, n) \n", " if n % m == 0])]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "[n for n in range(1, 50) \n", " if len([m for m in range(1, n + 1) \n", " if n % m == 0]) == 2]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "# A funkcionális programozás alapelemei\n", "Történelem: Guido van Rossum eredetileg ki kívánta dobni a funkcionális programozás alapelemeit a Python 3 core-ból a listaértelmezéssel helyettesíthetőnek tartva a fontosabbakat. A funkcionális programozás híveinek kemény ellenállását látva végül a lambda, map(), filter() maradt, de a reduce() kikerült az functools csomagba.\n", "## Lambda függvények\n", "\n", "Ha egyszerű műveleteket szeretnénk végezni függvényekkel, akkor ezekhez külön függvényt írni felesleges:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def negyzet(x):\n", " return x * x\n", "negyzet(5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "negyzet = lambda x: x*x\n", "print negyzet(6)\n", "\n", "(lambda x: x**3)(8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A lambda-függvénynek több argumentuma is lehet:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "osszeg = lambda a, b: a + b\n", "osszeg(2, 4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## map" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "L = [1, 5, 8]\n", "print map(negyzet, L)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "A map egy lista minden elemére alkalmazza a megadott függvényt." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "L = [1, 5, 8]\n", "print map(lambda x: x * x, L)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "A lambda függvény egy egysoros függvény, mely ilyen helyzetekben kényelmesen használható." ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## filter\n", "\n", "A filter függvény leszűr egy listát egy adott bool-függvény szerint." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "L = range(1, 10)\n", "print filter(lambda x: x % 2 == 0, L)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## reduce\n", "\n", "A reduce egy 2-változós függvényt alkalmaz egy iterálható objektum (pl. lista) elemeire balról jobbra haladva, míg végül egyetlen értéket nem kap. Alakja:\n", "\n", "reduce(*függvény*, *iterálható*[, *kezdő_érték*])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "osszeg = lambda a, b: a + b\n", "reduce(osszeg, [1, 2, 3, 4])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A harmadik opcionális argumentum egy kezdőérték megadását teszi lehetővé, ami a 2-változós függvény első végrehajtásakor a bal argumentumnak adódik át.\n", "Pl. egy számot osszunk el egy lista minden elemével. Egy lehetséges megoldás:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "szam = 30000\n", "osztok = [2, 2, 3, 5]\n", " \n", "kisszam = szam\n", "for oszto in osztok:\n", " kisszam = kisszam / oszto\n", " \n", "print kisszam" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Most ez reduce-szal:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "def oszt(a, b):\n", " return a/b\n", " \n", "print reduce(oszt, osztok, szam)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "plusz lambda függvénnyel:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "reduce(lambda a, b : a / b, osztok, szam)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## lambda, map() és filter() listaértelmezéssel" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "lista = [2, 3, 5, 8]\n", "[x**2 for x in lista]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "lista = range(10)\n", "[x for x in lista if x % 2 == 0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" } }, "nbformat": 4, "nbformat_minor": 0 }