1. fejezet
Sok adat egy névvel
Egy osztály 28 tanulójának jegyét nem tároljuk 28 külön változóban (jegy1, jegy2, …): egyetlen adatszerkezetbe tesszük őket, amelyen aztán ciklussal végig tudunk menni. A Python három alapvető, egymás mellett is használt adatszerkezetét ismered meg:
lista (list)
Sorrendben tárol, módosítható, ismétlődhet benne elem. Az általános „gyűjtő”.
tuple
Sorrendben tárol, de nem módosítható. Összetartozó, rögzített adatokhoz (pl. koordináta).
halmaz (set)
Csak egyedi elemek, sorrend nélkül. Ismétlődések kiszűréséhez, gyors kereséshez.
A Pythonnak van egy negyedik alapvető adatszerkezete is, a szótár (dict) – neki a 8. modult szenteljük.
2. fejezet
A lista és az indexelés
A listát szögletes zárójelek között, vesszővel elválasztott elemekkel hozzuk létre. Az elemek típusa vegyes is lehet, de a gyakorlatban egy listában általában azonos fajta adatok állnak. Az üres lista: []. Az elemek számát a len() adja meg.
jegyek = [5, 3, 4, 5, 2] nevek = ["Anna", "Béla", "Csilla"] ures = [] print(jegyek) print(len(jegyek), len(nevek), len(ures)) print(jegyek[0], jegyek[1], jegyek[4]) print(nevek[-1])
A lista elemeinek sorszáma az index, amely 0-tól indul: az első elem a lista[0], egy n elemű lista utolsó eleme a lista[n - 1]. A negatív index hátulról számol: lista[-1] az utolsó, lista[-2] az utolsó előtti elem.
Nem létező indexre IndexError a válasz. Egy 5 elemű listában nincs lista[5] – az utolsó a lista[4]. Ez a „0-tól indexelés” leggyakoribb csapdája.
jegyek = [5, 3, 4, 5, 2] print(jegyek[5])
Szeletelés
A lista[start:stop] egy új listát ad a start indextől a stop előttiig – ugyanúgy, mint a range()-nél, a stop már nem része. Bármelyik határ elhagyható (akkor az elejétől / a végéig), és harmadikként lépésköz is megadható. A szeletelés szövegre is működik, és sosem ad IndexError-t. Negatív lépésköznél a szelet hátulról indul, ezért a [::-1] a teljes sorozat megfordítva.
szamok = [10, 20, 30, 40, 50, 60] print(szamok[1:4]) print(szamok[:2]) print(szamok[3:]) print(szamok[::2]) print(szamok[::-1]) szo = "Python" print(szo[0], szo[-1], szo[:3])
A szöveg nem módosítható. A szöveg betűit indexeléssel olvashatod, de nem írhatod felül: a szo[0] = "p" TypeError. Módosított szöveghez új szöveget kell készíteni, például szeleteléssel és összefűzéssel: "p" + szo[1:].
szo = "Python"
print("p" + szo[1:])
szo[0] = "p"
Mit ír ki?
x = [3, 1, 4, 1, 5, 9] print(x[2:5], x[-2])
[1, 4, 1] 9[4, 1, 5] 5[4, 1, 5, 9] 5
A 2-es indexű elem a 4 (a harmadik!), a szelet az 5-ös index előtt áll meg: [4, 1, 5]. A x[-2] az utolsó előtti elem: 5.
3. fejezet
A lista módosítása és bejárása
A lista módosítható (mutable): egy eleme felülírható, és elemek adhatók hozzá vagy vehetők ki belőle – mindez helyben, ugyanabban a listában történik. A leggyakoribb műveletek (a többit a 6. modul mutatja be):
A lista.append(x) alakú hívás metódushívás: a pont előtti értékhez (itt a listához) tartozó műveletet futtatja. A metódus ugyanúgy hívható, mint egy függvény, de mindig egy konkrét értéken dolgozik – a kosar.append("tej") a kosar listát bővíti. A szövegeknek is vannak metódusaik ("alma".upper()); a 6. modul részletesen összeveti a függvényeket és a metódusokat.
| Művelet | Hatás |
|---|---|
lista[i] = x | az i-edik elem felülírása |
lista.append(x) | x hozzáadása a lista végéhez |
lista.insert(i, x) | x beszúrása az i-edik helyre (a többi hátrébb csúszik) |
lista.remove(x) | az első x értékű elem törlése (ha nincs: ValueError) |
lista.pop(), lista.pop(i) | az utolsó / az i-edik elem kivétele (vissza is adja) |
del lista[i] | az i-edik elem törlése |
x in lista | benne van-e (True/False) |
kosar = ["alma", "kenyér"]
kosar.append("tej")
kosar.insert(0, "sajt")
kosar[2] = "barna kenyér"
print(kosar)
kosar.remove("alma")
utolso = kosar.pop()
print(kosar, "– kivettük:", utolso)
print("tej" in kosar, "sajt" in kosar)
Kövesd lépésenként: a Memória részben a kosar változó egy nyíllal mutat a lista objektumra, és látod, ahogy a lista celláiba új elemek kerülnek, mások eltűnnek.
A lista bejárása
A for ciklus a lista elemein megy végig. Ha az indexre is szükség van (pl. sorszámozáshoz vagy egy elem módosításához), a range(len(lista)) adja a 0, 1, …, n−1 indexeket.
nevek = ["Anna", "Béla", "Csilla"]
for nev in nevek:
print("Szia,", nev)
for i in range(len(nevek)):
print(f"{i + 1}. {nevek[i]}")
Lista építése ciklussal
Nagyon gyakori minta: üres listából indulunk, és a ciklusban append()-del gyűjtjük bele az elemeket – például a beolvasott vagy egy feltételnek megfelelő értékeket.
szamok = []
szam = int(input("Szám (0 = vége): "))
while szam != 0:
szamok.append(szam)
szam = int(input("Szám (0 = vége): "))
parosak = []
for sz in szamok:
if sz % 2 == 0:
parosak.append(sz)
print("A számok:", szamok)
print("Ebből páros:", parosak)
4. fejezet
Hivatkozás és másolat – a lista nem ismétlődik meg magától
Az első modulban láttuk, hogy a b = a után az a megváltoztatása nem hat a b-re. Listáknál ez másképp látszik, és ez a kezdők egyik legnagyobb meglepetése:
a = [1, 2, 3]
b = a
b.append(4)
print("a:", a)
print("b:", b)
A Pythonban a változó egy névcédula, amely egy objektumra mutat. A b = a nem másolja le a listát: a b ugyanarra az egyetlen listára mutat, mint az a. Ha a listát helyben módosítjuk (append, b[0] = …), azt mindkét néven át látjuk. Kövesd lépésenként: a Memóriában két nyíl mutat ugyanarra a listára.
A számoknál és szövegeknél ez azért nem okoz gondot, mert ezek nem módosíthatók: a kor = kor + 1 nem a régi számot változtatja meg, hanem egy új értékhez köti a nevet. A lista viszont helyben is változhat.
Ha önálló másolat kell, kérjük kifejezetten: a.copy(), list(a) vagy a[:]. Ezek új külső listát készítenek: számokból vagy szövegekből álló listánál a két lista teljesen külön módosítható. Ha viszont a lista elemei maguk is listák (vagy más módosítható objektumok), a belső elemek közösek maradnak – ez a sekély másolat. A 8. modulban egy példán meg is nézzük.
eredeti = [1, 2, 3]
masolat = eredeti.copy()
masolat.append(4)
print("eredeti:", eredeti)
print("másolat:", masolat)
Mit ír ki?
x = [10, 20] y = x x = x + [30] print(y)
[10, 20, 30][30][10, 20]
Figyelj: az x + [30] nem módosítja a régi listát, hanem egy új listát hoz létre, és az x erre az újra fog mutatni. Az y továbbra is a régi, változatlan [10, 20]-ra mutat. (Az x.append(30) után viszont [10, 20, 30] lenne a válasz.) Kövesd lépésenként, és figyeld a nyilakat.
5. fejezet
A tuple
A tuple (magyarul néha „rendezett n-es”) olyan, mint egy lista, amely létrehozása után nem változtatható meg: nem írható felül eleme, nem bővíthető, nem törölhető belőle. Kerek zárójellel írjuk – de valójában a vessző teszi tuple-lé (kivétel az üres tuple: ()).
pont = (3, 4) szin = (255, 128, 0) egyelemu = (7,) nem_tuple = (7) print(pont[0], pont[1], len(szin)) print(type(egyelemu), type(nem_tuple)) koordinatak = 10, 20 print(koordinatak)
Az egyelemű tuple-höz vessző kell: a (7) csak egy zárójelbe tett szám, a (7,) a tuple. A módosítási kísérlet TypeError:
pont = (3, 4) pont[0] = 5
Kicsomagolás
A tuple (és a lista) elemei egyetlen értékadással szétoszthatók több változóba – a bal oldalon annyi név kell, ahány elem van. Ezzel egy sorban megoldható két változó cseréje is, segédváltozó nélkül: a jobb oldalon előbb elkészül a (b, a) tuple, és csak utána osztódik szét.
pont = (3, 4)
x, y = pont
print("x =", x, " y =", y)
a = "alma"
b = "körte"
a, b = b, a
print(a, b)
elso, *tobbi = [5, 8, 2, 7]
print(elso, tobbi)
Az utolsó sorban a * előtagú név „összegyűjti” a megmaradt elemeket egy listába: elso = 5, tobbi = [8, 2, 7].
Mire jó egy nem módosítható lista? Kifejezi a szándékot (egy pont két koordinátája összetartozik, és nem lesz belőle három), védi az adatot a véletlen módosítástól, és – mivel nem változhat – szótárkulcs vagy halmazelem is lehet (ha az elemei is megváltoztathatatlanok). A függvények is tuple-ben adnak vissza több értéket (7. modul).
6. fejezet
A halmaz (set)
A halmaz a matematikai halmazhoz hasonló: egy elem vagy benne van, vagy nincs – kétszer nem lehet benne, és az elemeknek nincs sorrendje, ezért indexelni sem lehet. Kapcsos zárójellel írjuk, az üres halmaz viszont set(), mert a {} üres szótárat jelent.
szinek = {"piros", "kék", "piros", "zöld"}
print(len(szinek))
print("kék" in szinek)
szinek.add("sárga")
szinek.discard("piros")
print(sorted(szinek))
jegyek = [5, 3, 5, 4, 3, 5]
print(set(jegyek))
print("Különböző jegyek száma:", len(set(jegyek)))
A halmaz kiírásakor az elemek sorrendje nem garantált (és futásról futásra is változhat szövegeknél). Ha rendezve akarod látni, használd a sorted() függvényt, amely az elemekből rendezett listát készít (bővebben a 6. modulban). A remove(x) hibát ad, ha x nincs a halmazban, a discard(x) nem.
Halmazműveletek
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
print("unió:", A | B)
print("metszet:", A & B)
print("különbség:", A - B)
print("szimmetrikus különbség:", A ^ B)
print("részhalmaz-e:", {1, 2} <= A)
7. fejezet
Melyiket mikor?
| lista | tuple | halmaz | |
|---|---|---|---|
| írásmód | [1, 2, 3] | (1, 2, 3) | {1, 2, 3} |
| üres | [] | () | set() |
| módosítható | igen | nem | igen (elem be/ki) |
| sorrend, index | van | van | nincs |
| ismétlődés | lehet | lehet | nem lehet |
| tipikus használat | beolvasott adatok, gyűjtés, rendezés | koordináta, összetartozó rögzített adatok, több visszatérési érték | egyedi elemek, „benne van-e?”, halmazműveletek |
Az átalakítás a típus nevével történik: list(...), tuple(...), set(...). Egy lista ismétlődéseit így lehet kiszűrni: list(set(lista)) – de vigyázz, a sorrend ilyenkor elveszhet.
8. fejezet
Gyakorló feladatok
Fordított sorrend
Olvass be pontosan 5 egész számot egy listába, majd írd ki őket fordított sorrendben, egy sorban, szóközzel elválasztva.
1. szám: 4 2. szám: 8 3. szám: 15 4. szám: 16 5. szám: 23 23 16 15 8 4
szamok = []
for i in range(1, 6):
szam = int(input(f"{i}. szám: "))
# tedd bele a listába!
# írd ki fordítva!
szamok = []
for i in range(1, 6):
szam = int(input(f"{i}. szám: "))
szamok.append(szam)
for szam in szamok[::-1]:
print(szam, end=" ")
print()
Tipp
Gyűjtsd append()-del, aztán járd be a szamok[::-1] szeletet (vagy indexekkel visszafelé: range(4, -1, -1)).
Szó darabjai
Kérj be egy (legalább 3 betűs) szót, és szeleteléssel írd ki az első három betűjét, az utolsó három betűjét és a szót visszafelé:
Szó: programozás
Eleje: pro
Vége: zás
Visszafelé: sázomargorp
szo = input("Szó: ")
print("Eleje:", szo[:3])
print("Vége:", szo[-3:])
print("Visszafelé:", szo[::-1])
Tipp
Eleje: [:3], vége: [-3:], fordítva: [::-1].
Szűrés két listába
Olvass be pozitív egész számokat 0 végjelig. Gyűjtsd a 10-nél kisebbeket az egyik, a többit a másik listába, és írd ki mindkét listát így:
Szám: 12 Szám: 7 Szám: 30 Szám: 0 Kicsik: [7] Nagyok: [12, 30]
kicsik = []
nagyok = []
szam = int(input("Szám: "))
while szam != 0:
if szam < 10:
kicsik.append(szam)
else:
nagyok.append(szam)
szam = int(input("Szám: "))
print("Kicsik:", kicsik)
print("Nagyok:", nagyok)
Tipp
Két üres listával kezdj. Végjelig olvasás: beolvasás a ciklus előtt és a mag végén. A listát a print() szögletes zárójellel, vesszővel írja ki – pont úgy, ahogy a minta kéri.
Két pont távolsága
Kérd be két síkbeli pont koordinátáit (valós számok), tárold őket egy-egy tuple-ben, és írd ki a távolságukat két tizedesjegyre. (Távolság: √((x₂ − x₁)² + (y₂ − y₁)²); a gyökvonás math.sqrt().)
P x: 1 P y: 2 Q x: 4 Q y: 6 P = (1.0, 2.0), Q = (4.0, 6.0) Távolság: 5.00
import math
p = (float(input("P x: ")), float(input("P y: ")))
q = (float(input("Q x: ")), float(input("Q y: ")))
dx = q[0] - p[0]
dy = q[1] - p[1]
tav = math.sqrt(dx ** 2 + dy ** 2)
print(f"P = {p}, Q = {q}")
print(f"Távolság: {tav:.2f}")
Tipp
Egy tuple két beolvasásból: p = (float(input(…)), float(input(…))). Az elemek: p[0], p[1] (vagy kicsomagolva: x1, y1 = p). A tuple kiírva (1.0, 2.0) alakú.
Hány különböző?
Kérd be, hány szót fogsz megadni, majd olvasd be őket. Írd ki, hány szót adtak meg összesen, és hány különböző szó volt köztük. (Kis- és nagybetű különbözőnek számít.)
Hány szó? 5 Szó: alma Szó: körte Szó: alma Szó: szilva Szó: körte Összesen 5 szó, ebből 3 különböző.
db = int(input("Hány szó? "))
szavak = []
for i in range(db):
szavak.append(input("Szó: "))
print(f"Összesen {len(szavak)} szó, ebből {len(set(szavak))} különböző.")
Tipp
A set(szavak) kiszűri az ismétlődéseket; a len() megadja, hány elem maradt.
Közös betűk
Kérj be két szót, és írd ki, mely betűk szerepelnek mindkettőben, illetve melyek csak az elsőben. A betűket rendezve (a sorted() függvénnyel) írd ki, egy-egy listaként. A sorted() a karakterkód szerint rendez, ezért az ékezetes betűk a lista végére kerülnek.
Első szó: kert Második szó: tér Közös: ['r', 't'] Csak az elsőben: ['e', 'k']
a = set(input("Első szó: "))
b = set(input("Második szó: "))
print("Közös:", sorted(a & b))
print("Csak az elsőben:", sorted(a - b))
Tipp
A set("alma") a betűk halmaza: {'a', 'l', 'm'}. A metszet &, a különbség -. A sorted() rendezett listát ad, így a kiírás mindig ugyanolyan sorrendű.
Javítsd a hibát: az eredeti ne változzon
Az alábbi program egy dolgozat pontszámaiból egy „javított” listát készít: minden 40 alatti pontszámot 40-re emel. A hiba: a javítás után az eredeti lista is megváltozik. Javítsd ki úgy, hogy az eredeti pontszámok változatlanok maradjanak. Kövesd lépésenként a kezdő kódot, és figyeld a nyilakat.
Eredeti: [35, 72, 18, 90] Javított: [40, 72, 40, 90]
eredeti = [35, 72, 18, 90]
javitott = eredeti
for i in range(len(javitott)):
if javitott[i] < 40:
javitott[i] = 40
print("Eredeti:", eredeti)
print("Javított:", javitott)
eredeti = [35, 72, 18, 90]
javitott = eredeti.copy()
for i in range(len(javitott)):
if javitott[i] < 40:
javitott[i] = 40
print("Eredeti:", eredeti)
print("Javított:", javitott)
Tipp
A javitott = eredeti nem másol, csak egy második nevet ad ugyanannak a listának. Másolat: eredeti.copy(), list(eredeti) vagy eredeti[:].
9. fejezet
Összefoglalás
| Fogalom | Lényeg |
|---|---|
| index | 0-tól indul; a -1 az utolsó elem; nem létező index: IndexError |
szelet [a:b:c] | új lista/szöveg; a b már nem része; [::-1] fordítva |
| lista | módosítható: append, insert, remove, pop, del, lista[i] = x |
| hivatkozás | b = a nem másol; másolat: a.copy() |
| tuple | nem módosítható; kicsomagolás: x, y = pont; csere: a, b = b, a |
| halmaz | egyedi elemek, nincs sorrend; | & - ^; üres: set() |
Gyakorold tovább: olvasd be egy osztály tanulóinak nevét végjelig (üres sor), majd írd ki a névsort sorszámozva, a leghosszabb nevet, és hogy volt-e két egyforma név. Melyik adatszerkezet kell melyik részhez?