Python-ban a kódban bárhol definiálható függvény, a def kulcsszóval.
Példa: Egy üzenetet kiíró függvény:
def jo():
    print("Jó reggelt!")
jo()
Példa: Üres függvény, mely nem csinál semmit, de meghívható (praktikus nagy program írásakor, ha már látjuk, hogy erre a függvényre szükség lesz, de ráér később megírni):
def fv_neve(n): # PEP-8: kis betűket, szavak közt _ betűt használjunk
    pass
fv_neve(5)
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):
    """ Négyzetre emeli egy lista elemeit.
    """
    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 következő, azonos számú szóközzel behúzott utasítások blokkja az, ami akkor fut le amikor meghívjuk a függényt.
A blokkon belül használható kulcsszó a return, amely hatására a függvény futása leáll és a return után írt kifejezés értéke lesz a függvény visszaadott értéke.
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)
A függvényünk meghívásának nem volt „nem kívánt mellékhatása”, de nézzük meg mi lesz, ha a következő kódot 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. Az ilyen megoldás lehetséges, de kerülendő.
A paramétereket vesszővel választjuk el.
Példa: Írjunk függvényt, mely két vektor skaláris szorzatát adja vissza eredményül. A vektorokat listákkal reprezentáljuk!
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:
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 (amit tekinthetünk első argumentumnak, ez áll a pont bal oldalán). 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 a függvény futásának befejezésére, és a return után írt kifejezés értékének visszaadására szolgál. Egy függvényblokkban több return utasítás is lehet.
def prim_e(n):
    """n: 1-nél nagyobb egész
       return: True, ha n prím, egyébként False
    """
    oszto = 2
    while oszto ** 2 <= n:
        if n % oszto == 0:
            return False
        oszto += 1
    return True
print(prim_e(4))
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 (pl. mert nincs is benne, vagy épp futás közben „elkerülte”), akkor None-t ad ki eredményül.
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]
l2 = l.sort()
print(l2, l)
def jo_estet():
    return "Jó estét!"
jo_estet()
jo()
a = jo()
b = jo_estet()
print("Visszaadott érték:", a, b)
Általunk írt függvényeket természetesen használhatunk más általunk írt függvényekben. Ez erősen ajánlott is.
Érdemes a 4-5 sornál sokkal hosszabb függvényeket kisebb függvényekből összerakni. Így a függvényeink rövidek és áttekinthetőbbek 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.
Fealadat: Írjunk egy függvényt, melynek bemenete egy lista, melyben megkeresi a legkisebb és legnagyobb elemeket, kimenete pedig egy másik lista, melyben a legkisebb és legnagyobb elemek mind ki vannak nullázva!
Hogyan futunk neki egy ilyen feladatnak?
Itt a következő részfeladatokra bontható:
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):
    # Shellow copy = részleges/sekély másolat, új példány azonos elemekkel
    uj_l = l[:]     # sekély másolat készítése (szeletekre bontással)
    for i in range(len(uj_l)):
        if uj_l[i] == elem:
            uj_l[i] = 0
    return uj_l
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
            
    uj_l = l[:]
    for i in range(len(uj_l)):
        if uj_l[i] == min_elem:
            uj_l[i] = 0
            
    for i in range(len(uj_l)):
        if uj_l[i] == max_elem:
            uj_l[i] = 0
            
    return uj_l
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):
    uj_l = l[:]
    for i in range(len(uj_l) - 1):
        for j in range(len(uj_l) - i - 1):
            if uj_l[j] > uj_l[j+1]:
                uj_l[j], uj_l[j+1] = uj_l[j+1], uj_l[j]
                # temp = uj_l[j]
                # uj_l[j] = uj_l[j+1]
                # uj_l[j+1] = temp
    return uj_l
buborek([2, 3, 1, 4, 6, 2, 9, 3, 1, 3, 1, 9, 3, 9])
buborek(list(range(10, 0, -1)))
Írjuk ki minden lépés után a rendezés aktuális állapotát:
def buborek_kiir(l):
    uj_l = l[:]
    for i in range(len(uj_l) - 1):
        for j in range(len(uj_l) - i - 1):
            print(uj_l)                      # Kiírás 
            if uj_l[j] > uj_l[j + 1]:
                uj_l[j], uj_l[j + 1] = uj_l[j+1], uj_l[j]
    return uj_l
buborek_kiir(list(range(5, 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ó.
Feladat: 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):
    uj_l = l[:]
    for i in range(len(uj_l) - 1):
        minindex = i + minimum_index(uj_l[i:])
        uj_l[i], uj_l[minindex] = uj_l[minindex], uj_l[i]
    return uj_l
min_rendez([2, 3, 1, 4, 6, 2, 9, 3, 1, 3, 1, 9, 3, 9])
min_rendez(list(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(list(range(5, 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.