Python-ban a kódban bárhol definiálható függvény, a def
kulcsszóval.
def fv_neve(n):
"... kód ..."
Ez egy függvény definíció, itt csak azt írjuk le, hogy mit csináljon a negyzetel
függvény, ha meghívjuk:
def negyzetel(L):
uj_L = []
for i in L:
uj_L.append(i*i)
return uj_L
A def
kulcsszó után a függvény nevét írjuk, utána zárójelekben felsoroljuk a bemeneti paramétereket. A kettőspont után új blokk kezdődik, mint például egy for
ciklusban, ez a blokk fut le amikor meghívjuk a függényt.
A blokkon belül új kulcsszó a return
mely hatására a függvény futása leáll és az eredménye a return
után írt kifejezéssel.
Egy függvényt a nevével tudunk meghívni, mely után zárójelekben a bemeneti argumentumokat kell felsorolni (itt csak egy lista a bemeneti argumentum):
negyzetel([4, 3, 5])
Természtesen egy változón is meg lehet hívni a függvényt:
szamok = [5, 1, 8]
negyzetelt_szamok = negyzetel(szamok)
print szamok, negyzetelt_szamok
Mivel "jól" volt megírva a függvényünk így semmi nem kívánt dolog nem történt, de nézzük meg mi lesz, ha ezt a megvalósítást használjuk:
def negyzetel2(L):
i = 0
while i < len(L):
L[i] = L[i] ** 2
i += 1
return L
szamok = [5, 1, 8]
negyzetelt_szamok = negyzetel2(szamok)
print szamok, negyzetelt_szamok
Tehát amilyen műveletet a függvényen belül végrehajtottunk a listán az a beadott argumentumon végrehajtódott, megváltozott a szamok
lista. Erről egy későbbi előadáson még részletesen beszélünk, addig is tudjunk róla, hogy ilyen is lehetséges.
A paramétereket vesszővel választjuk el:
def skalaris_szorzat(v1, v2):
osszeg = 0
for i in range(len(v1)):
osszeg += v1[i] * v2[i]
return osszeg
skalaris_szorzat([2, 3, 5], [1, 5, 2])
A paraméterek bármilyen típusúak lehetnek. Akárhány paramétere lehet egy függvénynek, akár nulla is, a zárójelek ebben az esetben is kellenek:
def ures_lista():
return []
L = ures_lista()
L.append(5)
print L
Első (felszínes) megközelítésben függvényről beszélünk, ha meghívásának módja: függvénynév, majd zárójelpárban az argumentumok felsorolása, metódusról, ha meghívásának módja: az objektum után pont, majd a metódus neve, majd zárójelben az argumentumok. Pl.:
L = [5, 2, 4]
L.sort()
print L
A sort
a pythonban egy beépített metódusa a listáknak, mely rendezi az adott listát. Jó példa, mert létezik függvény formában is:
L = [5, 2, 4]
ujL = sorted(L)
print L, ujL
A sorted
függvény nem rendezi az argumentumként adott listát, hanem visszaad egy rendezett listát.
Ez a legtöbbször igaz a beépített metódusokra és függvényekre, tehát a függvények nem módosítják a kapott változókat, míg a metódusok módosítják az objektumot (változót) amin meg vannak hívva (ami a pont bal oldalán áll). Ezt a konvenciót hasznos követni és csak olyan függvényeket írni, melyek nem módosítják a kapott változókat.
Metódus írásról később tanulunk.
return
használata¶A return
utasítás függvényből kilépését ki lehet használni, például:
def prim_e(n):
for oszto in range(2, n/2):
if n % oszto == 0:
return False
return True
print prim_e(15)
print prim_e(23)
Itt azt használtuk ki, hogy amint egy return
parancshoz ér a függvény azonnal kilép és visszaadja ezt az eredményt. Tehát amint találunk egy osztót azonnal visszatérünk a hamis eredménnyel. Igazzal pedig csak akkor térünk vissza, ha végigért a ciklus, azaz nem találtunk megfelelő osztót.
Megjegyzés: a break egy ciklusból lép ki (csak ciklusból és csak egyből), míg a return függvényből (csak egy függvényből, de annak bárhány ciklusából).
return
után állhat None
, jelezvén, hogy "semmit" adott vissza a függvény.
Ha egy függvény nem találkozik futása során return
paranccsal, akkor None
-t ad ki eredményül.
Például ha elfelejtünk return
-t írni vagy rossz helyre tesszük.
Megjegyzés: a .sort()
metódus eredénye None
, de mellékhatása, hogy közben rendezi a paraméterként kapott listát.
L = [3, 2, 1, 4]
l = L.sort()
print l, L
Általunk írt függvényeket természetesen használhatunk más általunk írt függvényekben. Ez erősen ajánlott is.
Érdemes 4-5 sornál hosszabb függvényeket mellőzni, pontosabban azokat kisebb függvényekből összerakni. Így a függvényeink rövidek és egyértelműek lesznek. A működésük derüljön ki a változók és magának a függvénynek a nevéből.
Nézzünk egy példát:
Írjunk egy függvényt, melynek bemenete egy lista, a függvény keresse meg a lista legkisebb és legnagyobb elemét és nullázza ki az összes valamelyikükkel azonos értéket a listában!
Hogyan futunk neki egy ilyen feladatnak?
Itt a következő részfeladatokra bontható:
Oldjuk is meg ezeket:
def minimum(L):
min_elem = float("inf")
for e in L:
if e < min_elem:
min_elem = e
return min_elem
def maximum(L):
max_elem = -float("inf")
for e in L:
if e > max_elem:
max_elem = e
return max_elem
def kinullaz(L, elem):
ujL = L[:] # Másolatot készítek a listáról (elejétől végéig részlista)
for i in range(len(ujL)):
if ujL[i] == elem:
ujL[i] = 0
return ujL
Most, hogy a részfeladatokat már megoldottuk nem maradt hátra más, mint hogy összerakjuk egybe a fő függvényt:
def min_max_nullaz(L):
minelem = minimum(L)
maxelem = maximum(L)
ujL = kinullaz(L, minelem)
ujL = kinullaz(ujL, maxelem)
return ujL
min_max_nullaz([2, 3, 1, 4, 6, 2, 9, 3, 1, 3, 1, 9, 3, 9])
min_max_nullaz([])
min_max_nullaz([1, 1, 1, 2])
Az utolsó három sor helyett írhattuk volna akár ezt is:
return kinullaz(kinullaz(L, minelem), maxelem)
Természetesen meg lehetett volna oldani ezt a feladatot egy függvénnyel is, itt az eredmény:
def min_max_nullaz2(L):
min_elem = float("inf")
for e in L:
if e < min_elem:
min_elem = e
max_elem = -float("inf")
for e in L:
if e > max_elem:
max_elem = e
ujL = L[:] # Másolatot készítek a listáról (elejétől végéig részlista)
for i in range(len(ujL)):
if ujL[i] == min_elem:
ujL[i] = 0
for i in range(len(ujL)):
if ujL[i] == max_elem:
ujL[i] = 0
return ujL
min_max_nullaz2([2, 3, 1, 4, 6, 2, 9, 3, 1, 3, 1, 9, 3, 9])
Az első megoldás:
Bár a második megoldás is működik.
def buborek(L):
ujL = L[:]
for i in range(len(ujL) - 1):
for j in range(len(ujL) - i - 1):
if ujL[j] > ujL[j + 1]:
temp = ujL[j]
ujL[j] = ujL[j + 1]
ujL[j + 1] = temp
return ujL
buborek([2, 3, 1, 4, 6, 2, 9, 3, 1, 3, 1, 9, 3, 9])
buborek(range(10, 0, -1))
Írjuk ki minden lépés után a rendezés aktuális állapotát:
def buborek_kiir(L):
ujL = L[:]
for i in range(len(ujL) - 1):
for j in range(len(ujL) - i - 1):
print ujL # Kiírás
if ujL[j] > ujL[j + 1]:
temp = ujL[j]
ujL[j] = ujL[j + 1]
ujL[j + 1] = temp
return ujL
buborek_kiir(range(10, 0, -1))
Ennél hatékonyabb algoritmusok léteznek a keresésre, ezekről részletesebben az Algoritmuselmélet című tárgyban lesz szó.
Valósítsuk meg még azt az ötletet, hogy egyesével megkessük a legkisebb, a második legkisebb, stb. elemet és ezeket a megfelelő helyre tesszük.
def minimum_index(L):
min_index = 0
for i in range(len(L)):
if L[i] < L[min_index]:
min_index = i
return min_index
def min_rendez(L):
ujL = L[:]
for i in range(len(ujL) - 1):
minindex = i + minimum_index(ujL[i:])
ujL[i], ujL[minindex] = ujL[minindex], ujL[i]
return ujL
min_rendez([2, 3, 1, 4, 6, 2, 9, 3, 1, 3, 1, 9, 3, 9])
min_rendez(range(10, 0, -1))
def min_rendez_kiir(L):
ujL = L[:]
for i in range(len(ujL) - 1):
print ujL
minindex = i + minimum_index(ujL[i:])
ujL[i], ujL[minindex] = ujL[minindex], ujL[i]
return ujL
min_rendez_kiir(range(10, 0, -1))
min_rendez_kiir([4, 5, 2, 3, 6, 7, 1])
A kiírástól csalóka lehet, mert kevesebb kimenetet kaptunk, ez azért van, mert itt csak a külső for
ciklusban van a kiírás, nem a belsőben. Itt a belső ciklus el van rejtve a minimum_index
függvényben.