6. hét: függvények

Czirkos Zoltán, Frey Balázs · 2022.10.06.

Függvények, paraméterek és visszatérési értékek. Kód refaktorálása, kódrészletek kiemelése különálló függvényekbe.

1. Második Kis ZH

A hétfői alkalmakon lesz a második kis ZH.

Jelentkeztél NZH-ra? Nézted a nagy házik listáját? Ne feledd, ezek határidős feladatok!

2. main()

Az alábbi feladatok programjai a legtöbb helyen nem tartalmaznak main() függvényt. Ahol nem kéri külön a feladat, ott is add hozzá! A következő héttől kezdve minden kódban, minden ZH-ban kérjük és pontozzuk a main() függvény használatát.

3. Függvények – alapok

Írj függvényeket, amelyek valós számot vesznek át, és visszatérnek a:

  • kob() – harmadik hatványával,
  • abszolut() – abszolút értékével (van beépített abs() függvény, de most ne használd)!

Írj programot, amelyik a = −1-től +1-ig, tizedenként lépve, kiírja egymás mellé a, a3, |a| és sin(a) értékét, mindig négy tizedesjegy pontossággal!

4. Szökőév

Készíts függvényt, amelyik adott évszámról eldönti, hogy az szökőév-e. Szökőév minden negyedik, nem szökőév minden századik, mégis az minden 400-adik. (2000-ben ezért volt szökőév.) A függvény visszatérési értéke legyen logikai típusú!

Írj programot, amelyik a felhasználótól évszámokat kér, és mindegyikre kiírja, hogy szökőév-e! Például:

? 2005
Nem szökőév.

? 2000
Szökőév.

? 1980
Szökőév.

? 1900
Nem szökőév.
Megoldás

Egyformán jó megoldások:

def szokoev(ev):
    return ev % 400 == 0 or (ev % 4 == 0 and ev % 100 != 0)
def szokoev(ev):
    if ev % 400 == 0:
        return True
    if ev % 4 == 0 and ev % 100 != 0:
        return True
    return False

5. Az év napja

Írj programot, amely megkérdezi a felhasználótól egy hónap számát (pl. 3 = március), és utána kiírja, hány napos az a hónap!

Megoldás

A megoldás terve

  • A gép nem tudja magától, hogy melyik hónap hány napos, ezt nekünk kell megadni.
  • Hozzunk létre egy listát, tároljuk el a hosszakat!

Figyelni kell itt, hogy mindig a hónap - 1 indexet használjuk a listán, mivel a január, vagyis az 1-es hónap adata a 0. indexű elemben van, tehát hosszak[hónap - 1] = hónap hossza módon használhatjuk az adatszerkezetünket.

01234567891011
312831303130313130313031

Ezt úgy is meg lehetne oldani, ha a 0. indexű elembe betennénk egy helytartót, pl. egy 0 értéket. Mert akkor a januárhoz tartozó 31-es szám az 1. indexre kerülne, a február 28-a a 2. indexre stb. A példamegoldás nem ilyen.

honapok = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
honap = int(input("Kerem a hónap számát: "))
print(f"A kért hónap {honapok[honap-1]} db napból áll.")

Írj programot, amelyik egy adott dátumról (év, hónap, nap) kiírja, hogy az év hányadik napja! Az év paraméterre a szökőévek miatt van szükség. Használd fel az előző feladatban megírt függvényed!

Végül tedd be az év napját kiszámító algoritmusod is egy függvénybe! Vagyis az evnapja(ev, honap, nap) függvényhívás visszatérési értékében adja meg a nap sorszámát 1 és 365 (szökőév esetén 366) között.

Megoldás

A megoldás terve

  • Össze kell adni az eltelt hónapokat, és az adott napot. Például március 5. = 31 (január) + 28 (február) + 5 (ötödike) = az év 64. napja.
  • A hónapok hosszait az előző programban már eltároltuk egy listában. Annak az elejét kell majd összegezni.
  • Szökőéveknél a február 29 napos. Ezt akkor kell figyelembe venni, ha a február eltelt.
def szokoev(ev):
    return ev % 400 == 0 or (ev % 4 == 0 and ev % 100 != 0)

def evnapja(ev, honap, nap):
    honapok = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

    # hónapok összege
    napszam = 0
    i = 0
    while i < honap - 1:
        napszam += honapok[i]
        i += 1
    # +1, ha szökőév és február eltelt
    if szokoev(ev) and honap > 2:
        napszam += 1
    # az adott hónap napja
    napszam += nap
    return napszam

def main():
    ev = int(input("Kerem az évet: "))
    honap = int(input("Kerem a hónapot: "))
    nap = int(input("Kerem a napot: "))

    n = evnapja(ev, honap, nap)
    print(f"{ev}.{honap}.{nap}. az év {n}. napja")
main()

6. „a” betűvel kezdődő sztring

Egy olyan függvényt kell írnod, amely paraméterként sztringek listáját kapja. Meg kell vizsgálnia a listában található sztringeket, és megválaszolnia ezt a kérdést: van-e olyan sztring, amelyik „a” betűvel kezdődik! Ennek is legyen logikai típusú a visszatérési értéke.

Ügyelj arra, hogy a függvény helyesen működjön abban az esetben is, ha üres sztring van a listában!

Példák:

  • ["körte", "alma", "barack"] – van „a” betűvel kezdődő szó.
  • ["dinnye", "papaja", "", "zeller"] – nincs „a” betűvel kezdődő szó.
  • [] – nincs „a” betűvel kezdődő szó.

Teszteld a függvényed ezekkel a példákkal, kiírva a listákat és a függvény visszatérési értékét is a főprogramban!

7. Betű cseréje

A programodban egy szót fogsz kapni, továbbá egy pozíciót (indexet), és egy betűt, amire az adott helyen a karaktert cserélni kell. Például a „papa” szó 1-es indexű betűjét „i”-re cserélve a „pipa” szót kapjuk.

Írj függvényt, aminek paraméterei a szó, a pozíció és a betű! Végezze el a függvény a cserét! Hívd meg a főprogramból a függvényt (például a fenti adatokkal), és írasd ki a főprogramból a megváltoztatott sztringet!

Tipp – ha elakadtál

A Pythonban a sztringek immutábilis objektumok, vagyis a tartalmukat nem lehet módosítani. Ezért nem létezhet olyan, hogy indexeléssel, értékadással megváltoztatunk benne egy karaktert, hiába adódik át referencia szerint a függvény paramétereként a sztring is. Új sztringet kell visszaadni a függvényből.

Tipp – ha nincs ötleted

Mivel a sztring tartalma nem módosítható, új sztringet kell létrehozni: eleje + megváltoztatott kararakter + vége.

Egészítsd ki úgy a függvényed, hogy figyelembe vegye az érvénytelen indexeket, és azokra dobjon kivételt! Tehát pl. „papa→pipa”, ha az 1-es indexű karaktert kell cserélni, de dobj kivételt „Érvénytelen pozíció: X” üzenettel, ha mondjuk a 9-es vagy a –5-ös karakter cseréjét kérné a hívó! Az X helyére mindig íródjon a helytelen index. Kapd is el ezt a kivételt a főprogramban!

Megoldás
def cserel(szo, hol, mire):
    if hol < 0 or hol >= len(szo):
        raise ValueError("Érvénytelen pozíció: " + str(hol))
    return szo[0:hol] + mire + szo[hol+1:]

def main():
    uj = cserel("papa", 1, "i")
    print(uj)
    try:
        uj = cserel("papa", -5, "i")
        print(uj)
    except ValueError as e:
        print(e)
    
main()

8. Átlagnál kisebbek

Az alábbi program a megadott számsorból az átlagnál kisebbeket gyűjti egy listába:

szamok = [24, 31, 22, 43, 10, 84, 38, 44, 84, 56, 67, 51, 56, 84, 31, 65, 69, 83, 39]
szum = 0
db = 0
for x in szamok:
    szum += x
    db += 1
atlag = szum / db
szurt = []
for x in szamok:
    if x < atlag:
        szurt.append(x)
print(szurt)

Értsd meg a működését, utána pedig darabold fel függvényekre! Válaszd külön az átlagszámítás és a szűrés műveletét! Ahol lehet, használd a Python már tanult függvényeit! Például a lista hosszát nem úgy szoktuk meghatározni, hogy megszámoljuk az elemeit egyesével, de más részfeladatokra is találsz beépített függvényeket.

Megoldás
def atlag(szamok):
    return sum(szamok) / len(szamok)

def kisebbek_szurese(szamok, minel):
    szurt = []
    for x in szamok:
        if x < minel:
            szurt.append(x)
    return szurt

def atlagnal_kisebbek(szamok):
    return kisebbek_szurese(szamok, atlag(szamok))

def main():
    szamok = [24, 31, 22, 43, 10, 84, 38, 44, 84, 56, 67, 51, 56, 84, 31, 65, 69, 83, 39]
    print(atlagnal_kisebbek(szamok))

main()

9. Menüvezérelt program

Készíts egyszerű menüvezérelt programot! A program tároljon el egy számot, melynek kezdőértéke a = 1. Ezt követően a program jelenítse meg a képernyőn a értékét, és az alább látható menüt. A megfelelő menüpont számának megadása után hajtsa végre a-n a kiválasztott műveletet, írja ki újból a új értékét és a menüt! A menüből mindaddig lehessen újból választani, míg a kilépést nem választja a felhasználó!

print("0. Alapertek visszaallitasa (a = 1)",
      "1. Hozzaad 1-et",
      "2. Megforditja az elojelet",
      "3. Szorozza 2-vel",
      "9. Kilepes",
      sep="\n")

Minden egyes tevékenységet (műveletet) egy pici függvény valósítson meg, amelynek bemenő paramétere az a változó tartalma, visszatérési értéke pedig a megváltozott szám! A main() ezen függvények hívásával végezze el a feladatát!

Miért olyan lényeges ez a feladat?

Figyeld meg a kapott főprogramot! Ez irányítja a többi függvény működését: meghívja az egyes részfeladatokhoz tartozó alprogramokat, amelyek dolgukat végezve visszatérnek, újra a főprogram kezébe adva az irányítást. A főprogram és az alprogramok a paramétereken és a visszatérési értékeken keresztül kommunikálnak.

10. Madárnyelv

Adott az alábbi program, amely madárnyelven (mavadávárnyevelveven) írja ki a beírt szöveget.

szoveg = input()
for c in szoveg:
    if c == 'a' or c == 'e' or c == 'i' or c == 'o' or c == 'u':
        print(c, 'v', c, sep="", end="")
    else:
        print(c, end="")

Írj függvényt, amelyik megmondja egy betűről, hogy magánhangzó-e! Alakítsd át úgy a programot, hogy a megírt függvényt használod a main()-ben! A magánhangzós függvény megírható egyetlen egy sorból is (a fejlécén túl, természetesen).

Végezz el egy további átalakítást is: a madárnyelvesítés is legyen függvény! Vagyis írj egy olyan függvényt, amely paraméterként egy sztringet kap, visszatérési értéke is egy sztring; például madarnyelv("alma") == "avalmava". (A sztring összeállításához a += operátort tudod használni.) Használd fel ezt a függvényt a main()-ben az eredeti feladat megoldására!

Hogyan lehetne megoldani azt, hogy a nagybetűvel kezdődő szavakat is helyesen kezelje a program? Pl. az „Alma” szóra azt kell kiírnia, hogy „Avalmava”. Ehhez fel kell tudnia ismerni a nagybetűvel írt magánhangzókat is. Ugyanakkor az ismételt magánhangzó már a szó közepén van, tehát kisbetűsíteni kell.

Megoldás
def maganhangzo(c):
    return c == 'a' or c == 'e' or c == 'i' or c == 'o' or c == 'u'

def madarnyelv(szoveg):
    uj = ""
    for c in szoveg:
        if maganhangzo(c.lower()):
            uj = uj + c + 'v' + c.lower()
        else:
            uj += c
    return uj

def main():
    szoveg = input()
    print(madarnyelv(szoveg))

main()

11. Alapértelmezett paraméterek

A range() függvény három különféle paraméterezéssel hívható:

  • range(min, max): például a range(1, 5)-ből az 1, 2, 3, 4 számok potyognak ki.
  • range(min, max, step): adott lépésközzel, például range(0, 5, 2) paraméterek esetén 0, 2, 4.
  • range(max): egy paraméter esetén a kezdeti érték nulla lesz. Például range(3) esetén 0, 1, 2.

Írj függvényt szamtani() néven, amely egy számtani sorozatot ír ki a képernyőre! A paraméterezése legyen pontosan ugyanaz, mint a range() függvényé, vagyis pont ugyanazokat a számokat írd ki.

A függvény belsejében ne használd a range()-et, és ne is építs listát! A feladat lényege az, hogy lásd, hogyan kell eltérő paraméterszámmal hívható függvényt írni.

Tipp

Adj a paramétereknek None alapértelmezett értéket, és ellenőrizd meglétüket az xyz is None kifejezéssel!