{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Függvényhívás\n",
"Mi történik függvényhíváskor? Ismerős példa:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"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": {},
"source": [
"Itt egyszerűen az [5, 1, 8]
lista elemeit emeljük négyzetre.\n",
"\n",
"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": {},
"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": {},
"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": {},
"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": {},
"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": {},
"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": {},
"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.\n",
"\n",
"Ahhoz, hogy a lista elemei is lemásolódjanak, mást kell csinálnunk."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L = [1,2,3]\n",
"M = L[:]\n",
"M[1] = 9\n",
"print L\n",
"print M"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Még bonyolultab a helyzet a tömbbel (listák listájával)!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"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": {},
"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": {},
"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": {},
"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": {},
"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."
]
},
{
"cell_type": "markdown",
"metadata": {},
"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. De ha mi írunk egy saját osztályt, annak példányai is objektumok.\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": {},
"outputs": [],
"source": [
"L1 = [1, 5, 2]\n",
"L2 = L1\n",
"\n",
"L2.sort()\n",
"print L1\n",
"print L2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ebben a példában L1
és L2
is ugyanarra az objektumra, egy listára mutat.\n",
"\n",
"Nem ez a helytet számokkal (melyek egyszerűbb objektumok). Azok értékek, nem pedig referenciák."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = 5\n",
"y = x\n",
"y = 6\n",
"print x, y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Extra függvény paraméterek\n",
"\n",
"### Opcionális változó\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": {},
"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": {},
"source": [
"Ekkor csinálhatjuk a következőt:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"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": {},
"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": {},
"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, 40)\n",
"print atmentek(hallgatok, 40, False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A következő hibás, mert a ponthatárt állítjuk False-ra:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print atmentek(hallgatok, False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Nevesített paraméter\n",
"\n",
"Lehet nevükkel hivatkozni az opcionális paramétereket! Ekkor sorrendjük nem számít, de azt a nevet kell írni az =
bal oldalára, amit a függvény megírásakor kitaláltunk."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print atmentek(hallgatok, sorban=False)\n",
"print atmentek(hallgatok, sorban=False, ponthatar=40)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print \"P({x}, {y}) pont\".format(y=3, x=4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Változó számú változó\n",
"\n",
"Láttunk már olyan függvényt, ami összeszoroz számokat. Egy listát kapott és a benne lévő számok szorzatát adta vissza."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def product(L):\n",
" eredmeny = 1\n",
" for i in L:\n",
" eredmeny *= i\n",
" return eredmeny\n",
"\n",
"print product([1,2,3])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Mi lenne ha a szorzata maga többváltozós lenne, nem pedig egyetlem lista változós?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def product2(x=1, y=1, z=1):\n",
" return x*y*z\n",
"\n",
"print product2()\n",
"print product2(1)\n",
"print product2(1, 2)\n",
"print product2(1, 2, 3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ez sajnos nem működik több változóra, csak ha kézzel hozzáfűzünk egy csomó opcionális paramétert.\n",
"\n",
"Ehelyett van a [variadikus](https://en.wikipedia.org/wiki/Variadic_function), vagy **váltózó számú paraméter**rel rendelkező függvény!\n",
"\n",
"Figyeljük meg, hogy az egyetlen különbség az eredeti product
függvényhez képest a *
"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def product3(*szamok):\n",
" eredmeny = 1\n",
" for i in szamok:\n",
" eredmeny *= i\n",
" return eredmeny\n",
"\n",
"print product3(1,2,3)\n",
"print product3(1, 2, 3, 4, 5, 6)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ekkor a beírt paramétereket egy tuple-ben kapja meg a függvényünk. Ez lehet 0, 1 vagy több elemű is, de _iterálhattó_."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def variadic(*x):\n",
" return type(x)\n",
"\n",
"print variadic(3,2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Variadikus függvény meghívása\n",
"Mi van ha egy variadikus függvényt akarunk megívni, de az argumenumok már egy listába vannak és szát kell őket szedni paraméterekké?\n",
"\n",
"Ekkor ez nem jó:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L = [1, 2, 3]\n",
"print product3(L)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Jó\n",
"print product3(*L)\n",
"\n",
"# ez ekvivalens ezzel de bárhány elemmel működik:\n",
"print product3(L[0], L[1], L[2])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Láthatóság\n",
"scope\n",
"\n",
"Hívhatunk azonos névvel kölünböző változókat, ha más helyen vannak, de ekkor fennáll a veszélye, hogy összekeverednek."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def fuggveny(L):\n",
" # i nem keveredik össze\n",
" for i in L:\n",
" if i <> 0:\n",
" return True\n",
" return False\n",
"i = [0, 1, -1]\n",
"print fuggveny(i)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def valami(L):\n",
" # összekeveredik\n",
" i = 0\n",
" for i in L:\n",
" i = i+i\n",
" return i\n",
"print valami([1, 2, 3])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def valami2(L):\n",
" i = 0\n",
" for j in L:\n",
" i = i+j\n",
" return i\n",
"\n",
"# nem keveredik össze\n",
"i = 10\n",
"print valami2([1, 2, 3])\n",
"print i"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ha egy változót egy **függvény belsejében** hozunk létre, akkor ott az fog látszódni, akkor is, ha volt olyan nevű változónk máshol. Ez a változó megszűnik létezni, amikor a függvény befejezi futását (a `return után`) és nem változtatja az esetlegeen meglévő ugyanolyan nevű fáltozónkat.\n",
"\n",
"Söt a függvény többszöri meghívásával újra létrejön, nem jegyzi meg értékét a függvényhívások között."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ha egy változót nem függvényben hozunk létre, akkor az minden más helyen látszódni fog. Függvény belsejében is, hacsak nem hozunk létre ott új változót."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"i = 10\n",
"def f(x):\n",
" # i = 0 # ez új i-t hozna létre\n",
" print i\n",
" \n",
"f(None)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Elágazásnál (if
) figyeljünk, hogy a változó nem mindig jön létre, egyes ágakban létrejöhet, másokban nem."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def f(x):\n",
" if x:\n",
" i = 0\n",
" return i\n",
" \n",
"print f(True)\n",
"print f(False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"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": {},
"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": {},
"source": [
"Módosítsuk ezt úgy, hogy bármilyen rendezésre működjön:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"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": {},
"source": [
"Ha már itt tartunk, akkor kiegészíthetjük opcionális paraméterrel is:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"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": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"type(novekvo)"
]
},
{
"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.15"
}
},
"nbformat": 4,
"nbformat_minor": 1
}