06. MODUL · PYTHON

Listakezelő függvények.

Beépített függvények és listametódusok

1. fejezet

Függvény vagy metódus? Új lista vagy helyben módosítás?

A listákkal kétféle eszközzel dolgozunk, és a kettőt érdemes már az írásmódjukról felismerni:

len(lista)

beépített függvény

A lista a zárójelbe kerül, argumentumként. Ilyen a len, sum, min, max, sorted.

lista.append(x)

metódus

A lista „saját” művelete, ponttal kapcsolódik hozzá. Ilyen az append, sort, pop, remove…

A másik fontos különbség, hogy a művelet új értéket ad vissza, vagy a meglévő listát helyben módosítja. Az itt tárgyalt beépített függvények (len, sum, min, max, sorted) nem változtatják meg a listát; a módosító metódusok viszont igen – és ezek többnyire None-t adnak vissza.

szamok = [5, 2, 8, 1]
rendezett = sorted(szamok)
print("sorted után:", szamok, rendezett)
szamok.sort()
print("sort után:", szamok)

Kövesd lépésenként: a sorted() után a Memóriában két külön lista van, a sort() után viszont ugyanaz az egy lista rendeződik át.

2. fejezet

Összesítés: len(), sum(), min(), max()

A 3. modulban ciklussal írtuk meg az összegzést és a maximumkeresést. A Pythonban ezekre kész függvények vannak – a ciklusos változatot azért érdemes ismerni, mert sokszor nem pontosan ezek kellenek (pl. „a páros számok összege”).

homersekletek = [12.5, 15.0, 9.5, 18.0, 14.0]
print("mérések száma:", len(homersekletek))
print("összeg:", sum(homersekletek))
print("legkisebb:", min(homersekletek))
print("legnagyobb:", max(homersekletek))
atlag = sum(homersekletek) / len(homersekletek)
print(f"átlag: {atlag:.2f}")
print(max(3, 9, 4), min("alma", "körte"))

Üres listán a min() és a max() ValueError-t ad, és az átlagnál nullával osztanánk. A sum([]) viszont 0. Ha a lista üres lehet, előbb vizsgáld meg: if len(lista) > 0: (vagy röviden if lista:, mert az üres lista hamisnak számít).

A min() és max() szövegeken a karakterkódok szerint dönt: max(["alma", "Banán"]) az "alma", mert a kisbetűk kódja nagyobb a nagybetűkénél. Ugyanez a szabály érvényes a rendezésre is.

3. fejezet

Rendezés és megfordítás

új listát ad, az eredeti maradhelyben módosít, eredménye None
rendezéssorted(lista)lista.sort()
csökkenő rendezéssorted(lista, reverse=True)lista.sort(reverse=True)
megfordításlista[::-1]lista.reverse()
pontok = [72, 95, 58, 88, 95, 61]
print(sorted(pontok))
print(sorted(pontok, reverse=True))
print("Dobogó:", sorted(pontok, reverse=True)[:3])
nevek = ["Zoli", "anna", "Béla", "Ádám"]
print(sorted(nevek))
pontok.reverse()
print(pontok)

A klasszikus hiba: lista = lista.sort(). A sort() helyben rendez és None-t ad vissza, így a lista változóba a None kerül – a rendezett lista elveszik. Vagy lista.sort() (egymagában), vagy lista = sorted(lista).

lista = [3, 1, 2]
lista = lista.sort()
print(lista)
print(len(lista))

A rendezés a karakterkód szerint halad, ezért a nagybetűs szavak a kisbetűsek elé kerülnek, és az ékezetes betűk (Á, É) a teljes ábécé végére. Magyar ábécérendhez külön eszköz kell (például a locale modul) – ez túlmutat ezen a tananyagon. Kis- és nagybetű nélküli rendezés: sorted(nevek, key=str.lower) – a key= után egy függvény neve áll zárójel nélkül; a rendezés ezt hívja meg minden elemre, és az eredmények szerint sorol.

Mit ír ki?

a = [3, 1, 2]
b = sorted(a)
a.append(0)
print(a, b)
  1. [3, 1, 2, 0] [0, 1, 2, 3]
  2. [3, 1, 2, 0] [1, 2, 3]
  3. [0, 1, 2, 3] [1, 2, 3]

A sorted(a) egy új, független listát hoz létre abban a pillanatban. A később hozzáfűzött 0 csak az a-ba kerül, a b-be nem; az a pedig nincs rendezve.

4. fejezet

Bővítés: append(), extend(), insert(), +

lista = [1, 2, 3]
lista.append(4)
lista.extend([5, 6])
lista.insert(0, 0)
print(lista)
uj = lista + [7, 8]
print(uj, len(lista), len(uj))
print([0] * 5)

append vagy extend? Az append egy elemet tesz a lista végére – ha ez az elem maga is egy lista, akkor egy belső listát kapsz. Az extend a másik sorozat elemeit fűzi egyenként a végére.

Mit ír ki?

a = [1, 2]
a.append([3, 4])
print(len(a), a)
  1. 4 [1, 2, 3, 4]
  2. 3 [1, 2, 3, 4]
  3. 3 [1, 2, [3, 4]]

Az append a [3, 4] listát egyetlen elemként teszi a végére, így a lista 3 elemű, és a harmadik elem maga is egy lista. Kövesd lépésenként: a Memóriában a külső lista harmadik cellájából egy nyíl mutat a belső listára.

5. fejezet

Törlés és keresés

MűveletMit csinál?Ha nincs ilyen elem
lista.pop()kiveszi és visszaadja az utolsó elemetüres listán IndexError
lista.pop(i)kiveszi és visszaadja az i-edik elemetIndexError
lista.remove(x)törli az első x értékű elemetValueError
del lista[i]törli az i-edik elemet (szeletet is: del lista[1:3])IndexError
lista.clear()minden elemet töröl–
x in listaTrue, ha x benne vanFalse
lista.count(x)hányszor szerepel x0
lista.index(x)x első előfordulásának indexeValueError
jegyek = [4, 5, 2, 5, 3, 5]
print("ötösök:", jegyek.count(5))
print("az első kettes helye:", jegyek.index(2))
jegyek.remove(5)
print(jegyek)
utolso = jegyek.pop()
print("kivett:", utolso, "maradt:", jegyek)
if 1 in jegyek:
    jegyek.remove(1)
else:
    print("Nincs egyes, nincs mit törölni.")

A remove() előtt érdemes in-nel ellenőrizni, hogy az elem benne van-e – különben a program ValueError-ral leáll.

Ne törölj abból a listából, amelyet éppen bejársz. A for ciklus indexek szerint halad; ha közben egy elem kiesik, a mögötte álló elemek egy hellyel előrébb csúsznak, és a ciklus egyet átugrik. Kövesd lépésenként:

szamok = [1, 2, 2, 3]
for x in szamok:
    if x == 2:
        szamok.remove(x)
print(szamok)

A második 2-es benne maradt. Helyes megoldás: új lista építése a megtartandó elemekből ([x for x in szamok if x != 2]), vagy a bejárás egy másolaton: for x in szamok[:]:.

6. fejezet

Szöveg és lista között: split() és join()

Ez a kettő a szöveg metódusa, nem a listáé – de pont a listák miatt használjuk őket olyan gyakran.

  • szoveg.split() a szöveget a szóközök (és tabulátorok, sortörések) mentén darabolja, és a darabokat listában adja vissza. szoveg.split(";") a megadott elválasztó mentén darabol. Figyelj a különbségre: a paraméter nélküli split() a többszörös szóközt is egy elválasztónak veszi, a split(" ") viszont minden egyes szóköznél vág: "4 8".split(" ") → ['4', '', '8'] – az üres darab az int()-nél hibát okoz.
  • elvalaszto.join(lista) a lista szövegeit fűzi össze egyetlen szöveggé, közéjük az elválasztót téve. Furcsának tűnhet, hogy az elválasztó áll elöl: ", ".join(gyumolcsok).
mondat = "A kertben terem alma és körte"
szavak = mondat.split()
print(szavak, len(szavak))
sor = "Kovács;Anna;17;Pécs"
adatok = sor.split(";")
print(adatok[1], adatok[3])
print(" – ".join(szavak))
print("".join(["P", "y", "t", "h", "o", "n"]))

Számok beolvasása egy sorból

Gyakori, hogy a felhasználó egy sorba írja a számokat, szóközzel elválasztva. A split() szövegek listáját adja (["4", "8", "15"]), ezért az elemeket egyenként számmá kell alakítani:

sor = input("Számok szóközzel elválasztva: ")
szamok = []
for darab in sor.split():
    szamok.append(int(darab))
print(szamok)
print("összeg:", sum(szamok), " legnagyobb:", max(szamok))

Rövidebben: listaértelmezés

A „vegyél minden elemet, alakítsd át, és gyűjtsd egy listába” minta annyira gyakori, hogy a Pythonnak külön, tömör írásmódja van rá, a listaértelmezés (list comprehension): szamok = [int(d) for d in sor.split()]. Pontosan ugyanazt csinálja, mint a fenti ciklus. Feltétel is írható bele: [x for x in szamok if x % 2 == 0] a páros számokat gyűjti ki.

A join() csak szövegeket fűz össze. A ", ".join([1, 2, 3]) TypeError-t ad – a számokat előbb szöveggé kell alakítani: ", ".join([str(x) for x in szamok]).

szamok = [1, 2, 3]
print(", ".join(szamok))

7. fejezet

Gyakorló feladatok

Statisztika egy sorból

Olvass be egy sornyi egész számot (szóközzel elválasztva), és írd ki a darabszámukat, az összegüket, a legkisebbet, a legnagyobbat és az átlagot két tizedesjegyre:

Számok: 12 7 30 5 9
Darab: 5
Összeg: 63
Legkisebb: 5
Legnagyobb: 30
Átlag: 12.60
szamok = []
for d in input("Számok: ").split():
    szamok.append(int(d))
print("Darab:", len(szamok))
print("Összeg:", sum(szamok))
print("Legkisebb:", min(szamok))
print("Legnagyobb:", max(szamok))
print(f"Átlag: {sum(szamok) / len(szamok):.2f}")
Tipp

Az input().split() szövegek listáját adja – alakítsd őket int()-tel számmá (ciklussal vagy listaértelmezéssel), utána jöhetnek a beépített függvények.

Ábécérend, eredeti sorrend

Olvass be egy sornyi szót, és írd ki őket három sorban: ábécérendben, fordított ábécérendben, végül az eredeti sorrendben. Mindegyik sorban vesszővel és szóközzel elválasztva.

Szavak: körte alma szilva barack
alma, barack, körte, szilva
szilva, körte, barack, alma
körte, alma, szilva, barack
szavak = input("Szavak: ").split()
print(", ".join(sorted(szavak)))
print(", ".join(sorted(szavak, reverse=True)))
print(", ".join(szavak))
Tipp

Ha a sort()-ot használnád, az eredeti sorrend elveszne – a harmadik sorhoz az kell. A sorted() új listát ad, a ", ".join(…) pedig összefűzi.

Felsorolás „és”-sel

Olvass be egy sornyi szót, és fűzd össze őket magyaros felsorolássá: az utolsó előtt „és”, a többi között vessző álljon. Egyetlen szónál csak magát a szót írd ki.

Szavak: alma körte szilva
alma, körte és szilva
szavak = input("Szavak: ").split()
if len(szavak) == 1:
    print(szavak[0])
else:
    print(", ".join(szavak[:-1]) + " és " + szavak[-1])
Tipp

Az utolsó előttiig: szavak[:-1], ezeket vesszővel fűzd össze; aztán jön az " és " és az utolsó szó (szavak[-1]). Két szónál a szavak[:-1] egyelemű – a join ilyenkor nem tesz vesszőt.

A legjobb három jegy átlaga

Olvass be egy sornyi érdemjegyet (legalább hármat), és írd ki a legjobb három jegyet csökkenő sorrendben, valamint ezek átlagát két tizedesjegyre:

Jegyek: 3 5 4 2 5 4
A legjobb három: [5, 5, 4]
Átlaguk: 4.67
jegyek = []
for d in input("Jegyek: ").split():
    jegyek.append(int(d))
legjobb = sorted(jegyek, reverse=True)[:3]
print("A legjobb három:", legjobb)
print(f"Átlaguk: {sum(legjobb) / 3:.2f}")
Tipp

Csökkenő rendezés, majd az első három: sorted(jegyek, reverse=True)[:3].

Ötösök és egyesek

Olvass be egy sornyi érdemjegyet. Írd ki, hány ötös van köztük, hányadik helyen áll az első egyes (1-től számozva; ha nincs egyes, ezt írd: Nincs egyes.), majd töröld a listából az összes egyest, és írd ki a maradékot.

Jegyek: 3 1 5 1 4
Ötösök: 1
Az első egyes helye: 2.
[3, 5, 4]
jegyek = []
for d in input("Jegyek: ").split():
    jegyek.append(int(d))
print("Ötösök:", jegyek.count(5))
if 1 in jegyek:
    print(f"Az első egyes helye: {jegyek.index(1) + 1}.")
else:
    print("Nincs egyes.")
while 1 in jegyek:
    jegyek.remove(1)
print(jegyek)
Tipp

jegyek.count(5), illetve jegyek.index(1) – az index 0-tól számol, ezért adj hozzá egyet. Az összes egyes törléséhez ismételd a remove(1)-et, amíg van egyes (while 1 in jegyek:), vagy építs új listát a nem egyes jegyekből.

Listaműveletek kombinálása

A program elején adott két lista. Fűzd az első végére a második elemeit fordított sorrendben, majd töröld az így kapott listából a legkisebb elemet, és írd ki a listát. A második lista maradjon változatlan.

[2, 3, 6, 5, 4]
A második lista: [4, 5, 6]
elso = [1, 2, 3]
masodik = [4, 5, 6]
# Ide jön a megoldás

print(elso)
print("A második lista:", masodik)
elso = [1, 2, 3]
masodik = [4, 5, 6]
elso.extend(masodik[::-1])
elso.remove(min(elso))
print(elso)
print("A második lista:", masodik)
Tipp

A masodik.reverse() a második listát is megfordítaná – a masodik[::-1] új, fordított listát ad. Ezt fűzd hozzá extend()-del, végül remove(min(elso)).

Ismétlődések nélkül, sorrendtartóan

Olvass be egy sornyi egész számot, és írd ki egy listában az elemeket úgy, hogy mindegyik csak az első előfordulásának helyén szerepeljen (a sorrend maradjon meg). Utána írd ki, hány elem volt ismétlődés.

Számok: 3 1 3 2 1 5 3
[3, 1, 2, 5]
Ismétlődés: 3
szamok = []
for d in input("Számok: ").split():
    szamok.append(int(d))
egyedi = []
for x in szamok:
    if x not in egyedi:
        egyedi.append(x)
print(egyedi)
print("Ismétlődés:", len(szamok) - len(egyedi))
Tipp

A set() itt nem jó, mert elveszítheti a sorrendet. Építs egy új listát: csak akkor tedd bele az elemet, ha még not in benne.

8. fejezet

Összefoglalás

CsoportEszközökMegjegyzés
összesítéslen, sum, min, maxüres listán a min/max hibát ad
rendezéssorted(l) / l.sort(), reverse=Truea sort() eredménye None
bővítésappend, extend, insert, +, *append: egy elem; extend: sok elem
törléspop, remove, del, clearremove: az első előfordulás
keresésin, count, indexindex: ValueError, ha nincs
szöveg ↔ listas.split(), "elv".join(l)join csak szövegeket fűz

Gyakorold tovább: egy sorban adott egy dolgozat összes pontszáma. Írd ki a medián pontszámot (a rendezett lista középső eleme; páros darabszámnál a két középső átlaga), és hogy hányan írtak az átlag fölött. Előbb számold ki kézzel egy 5 és egy 6 elemű példára.