1. fejezet
Miért kell ciklus?
Írd ki a számokat 1-től 5-ig. Ez még megy öt print-tel. És 1-től 1000-ig? Vagy annyiszor, ahányat a felhasználó kér? Az ilyen feladatokhoz ciklus kell: egy utasításcsoport, amelyet a program többször egymás után végrehajt.
A ciklus egy kódblokk ismételt végrehajtása. A megismételt, beljebb kezdett sorok a ciklusmag; a mag egy-egy lefutása egy ismétlés (iteráció). A Pythonban kétféle ciklus van: a for egy sorozat elemein halad végig, a while addig ismétel, amíg egy feltétel igaz.
for i in range(1, 6):
print(i, "a négyzete:", i * i)
print("Kész.")
Kövesd Lépésenként. A Memória részben figyeld az i változót: minden körben a következő értéket kapja. A „Kész.” sor nincs beljebb kezdve, ezért a ciklus után, egyszer fut le.
2. fejezet
A for ciklus
for valtozo in sorozat:
ciklusmag # minden elemre egyszer lefut
forkulcsszó: „minden … -ra/-re”valtozoa ciklusváltozó: körönként a sorozat következő elemein sorozatamin végighaladunk: range(), szöveg, lista…:+ behúzásutána jön a ciklusmag
A for annyiszor futtatja le a magot, ahány eleme a sorozatnak van, és minden körben a ciklusváltozóba teszi a soron következő elemet. A sorozat lehet például egy szöveg – ilyenkor a karaktereken megy végig:
szo = input("Adj meg egy szót: ")
for betu in szo:
print(betu)
…vagy egy lista (a listákról a 4. modulban lesz bővebben szó; itt elég annyi, hogy szögletes zárójelben, vesszővel felsorolt értékek):
for gyumolcs in ["alma", "körte", "szilva"]:
print("Kosárba tettem:", gyumolcs)
3. fejezet
Számsorozatok: range()
A leggyakoribb sorozat egy számtartomány. A range() függvény egy, két vagy három egész számot kap:
| Hívás | Számok | Jelentés |
|---|---|---|
range(5) | 0 1 2 3 4 | 0-tól 5-ig, az 5 már nem |
range(1, 6) | 1 2 3 4 5 | 1-től 6-ig, a 6 már nem |
range(0, 20, 5) | 0 5 10 15 | ötösével |
range(10, 0, -2) | 10 8 6 4 2 | visszafelé, kettesével |
A felső határ (stop) sosem része a sorozatnak. A range(1, 6) öt számot ad, 1-től 5-ig. Ennek az az előnye, hogy a range(n) pontosan n számot ad (0-tól n−1-ig), ezért „csináld meg n-szer” jelentésben is használható.
for mp in range(10, 0, -1):
print(mp, end=" ")
print("Start!")
Mit ír ki?
for i in range(2, 11, 3):
print(i, end=" ")
2 5 8 112 5 83 6 9
2-től indul, hármasával lép: 2, 5, 8. A következő a 11 lenne, de a stop (11) már nem része a sorozatnak.
4. fejezet
Ciklusminták: összegzés, számlálás, szélsőérték
A ciklusos feladatok nagy része néhány visszatérő mintára épül. Ha ezeket felismered, a legtöbb feladat megoldása már csak összerakás.
Összegzés
Egy gyűjtőváltozó a ciklus előtt 0-t kap, és a ciklusmagban minden körben hozzáadjuk az aktuális értéket. A osszeg += szam az osszeg = osszeg + szam rövidítése. Ugyanígy működik a -=, *=, /=, //= és %= is: például az x //= 10 jelentése x = x // 10.
n = int(input("Meddig adjam össze a számokat? "))
osszeg = 0
for szam in range(1, n + 1):
osszeg += szam
print(f"1 + 2 + … + {n} = {osszeg}")
Kövesd lépésenként n = 5-tel: az osszeg értéke 0 → 1 → 3 → 6 → 10 → 15. Figyeld meg a range(1, n + 1)-et: azért kell a + 1, mert a stop nem része a sorozatnak, mi pedig az n-et is össze akarjuk adni.
A gyűjtőváltozó kezdőértéke a ciklus előtt álljon. Ha az osszeg = 0 a ciklusmagba kerül, minden körben lenullázódik, és a végén csak az utolsó szám marad benne. Próbáld ki: tedd beljebb a sort, és kövesd lépésenként.
Számlálás
A számláló is a ciklus előtt kap 0-t, és csak akkor nő eggyel, ha az elem megfelel a feltételnek – ehhez a ciklusmagban egy if kell.
szoveg = input("Írj egy mondatot: ")
db = 0
for betu in szoveg.lower():
if betu in "aáeéiíoóöőuúüű":
db += 1
print("Magánhangzók száma:", db)
Két új apróság a példában: a szoveg.lower() a szöveg kisbetűs változatát adja (így a nagy kezdőbetű is magánhangzónak számít), a betu in "aáeé…" pedig igaz, ha a karakter szerepel a felsorolt szövegben – szövegnél az in azt vizsgálja, hogy a bal oldal része-e a jobb oldalnak.
Szélsőérték (legnagyobb, legkisebb)
A legnagyobb érték kereséséhez az első elemet tekintjük kezdetben a legnagyobbnak, majd minden további elemet összevetünk vele. Ha nagyobbat találunk, az lesz az új „eddigi legnagyobb”.
db = int(input("Hány számot adsz meg? "))
legnagyobb = int(input("1. szám: "))
for i in range(2, db + 1):
szam = int(input(f"{i}. szám: "))
if szam > legnagyobb:
legnagyobb = szam
print("A legnagyobb:", legnagyobb)
Miért nem 0 a legnagyobb kezdőértéke? Mert ha minden szám negatív, a 0 „győzne”, pedig nincs is a számok között. Az első tényleges elem mindig biztonságos kiindulópont.
5. fejezet
A while ciklus
while feltétel:
ciklusmag # addig ismétlődik, amíg a feltétel igaz
A while minden kör előtt kiértékeli a feltételt: ha igaz, lefut a mag, és utána újra a feltétel következik; ha hamis, a ciklus véget ér. Ha a feltétel már az elején hamis, a mag egyszer sem fut le. Akkor használjuk, amikor nem tudjuk előre, hány kör kell – például addig kérdezünk, amíg jó választ nem kapunk.
szam = 1
while szam <= 5:
print(szam)
szam += 1
print("A ciklus után szam =", szam)
Kövesd lépésenként: a Kiértékelés minden körben megmutatja a feltétel aktuális értékét. A ciklus utáni sorban a szam már 6 – éppen ez tette hamissá a feltételt.
Mit ír ki?
n = 0
db = 0
while n < 10:
n += 3
db += 1
print(n, db)
9 312 410 4
Az n értékei: 3, 6, 9, majd 12. A 9 után a feltétel (9 < 10) még igaz, ezért lefut egy negyedik kör is, és csak a 12-nél válik hamissá. A feltételt mindig a kör elején vizsgálja a Python – a „túllépés” a ciklus után látszik.
Példa: jelszó
jelszo = ""
while jelszo != "titok":
jelszo = input("Jelszó: ")
print("Beléptél.")
Az első sor (jelszo = "") azért kell, mert a feltétel kiértékelésekor a változónak már léteznie kell. Az üres szöveg biztosan nem egyezik a jelszóval, így legalább egyszer bekérjük.
Példa: végjelig olvasás
Gyakori feladat, hogy a felhasználó tetszőleges számú adatot ad meg, a végét pedig egy megbeszélt végjel (pl. 0) jelzi. A végjelet már nem dolgozzuk fel – ezért a beolvasás a ciklus előtt és a mag végén áll:
osszeg = 0
db = 0
szam = int(input("Szám (0 = vége): "))
while szam != 0:
osszeg += szam
db += 1
szam = int(input("Szám (0 = vége): "))
print(f"{db} számot adtál meg, az összegük {osszeg}.")
Végtelen ciklus. Ha a ciklusmag sosem teszi hamissá a feltételt, a ciklus soha nem ér véget. Az alábbi programból lemaradt a szam += 1. Futtasd: a tananyag felismeri és leállítja – a valódi gépen a terminálban Ctrl+C állítja meg. Javítsd ki.
szam = 1
while szam <= 5:
print(szam)
for vagy while?
Ha előre tudod, hányszor kell ismételni, vagy egy sorozat elemein mész végig: for. Ha egy feltétel teljesüléséig kell ismételni, és a körök száma a futás közben derül ki: while. Minden for átírható while-ra (számlálóval), de a for rövidebb, és nem lehet elfelejteni benne a léptetést.
6. fejezet
break és continue
A break azonnal kilép a ciklusból (a legbelsőből), a continue pedig a mag hátralévő részét kihagyja, és a következő körrel folytatja. Mindkettő általában egy if belsejében áll.
for i in range(1, 11):
if i % 3 == 0:
continue
if i > 7:
break
print(i, end=" ")
print()
A 3, 6 kimarad (continue), a 8-nál pedig a ciklus véget ér (break), így a 9 és a 10 már nem kerül sorra.
A while True + break minta
Bemenet ellenőrzésénél kényelmes, ha a ciklus „örökké” fut, és a jó adat beolvasása után break-kel lépünk ki. Így a beolvasás csak egyszer szerepel a kódban:
while True:
jegy = int(input("Érdemjegy (1–5): "))
if 1 <= jegy <= 5:
break
print("Hibás érték, próbáld újra!")
print("Rögzítve:", jegy)
7. fejezet
Beágyazott ciklusok
Egy ciklus magjában újabb ciklus is állhat. A belső ciklus a külső minden egyes körében végigfut. Táblázatokhoz, rácsokhoz, alakzatok rajzolásához használjuk.
for sor in range(1, 6):
for oszlop in range(1, 6):
print(f"{sor * oszlop:4}", end="")
print()
A belső ciklus egy sort ír ki egymás mellé (end=""), a sor végén a külső ciklus print()-je kezd új sort. A {…:4} formázás minden számot 4 karakter szélesre igazít, így az oszlopok egymás alá kerülnek. Összesen 5 · 5 = 25-ször fut le a belső mag.
Alakzatok: háromszög és fenyőfa
A "*" * db szövegismétlés sokszor kiváltja a belső ciklust. A fenyőfa i-edik sorában (az i 0-tól indul) magassag - i - 1 szóköz és 2 * i + 1 csillag áll – rajzold le papíron egy 4 magas fára, és ellenőrizd a képletet.
magassag = int(input("A fa magassága: "))
for i in range(magassag):
print(" " * (magassag - i - 1) + "*" * (2 * i + 1))
for i in range(2):
print(" " * (magassag - 2) + "|||")
Mit ír ki?
db = 0
for i in range(3):
for j in range(4):
db += 1
print(db)
74123
A külső ciklus 3-szor fut, és mindegyik körben a belső ciklus 4-szer: 3 · 4 = 12 növelés.
8. fejezet
Összefoglaló példa: számkitaláló játék
A gép gondol egy számra 1 és 100 között, a játékos legfeljebb 7-szer tippelhet, és minden tipp után megtudja, hogy a gondolt szám kisebb vagy nagyobb. A véletlenszámot a random modul randint() függvénye adja – a modult az 5. modulban részletesen megismered.
import random
gondolt = random.randint(1, 100)
max_tipp = 7
tippek = 0
eltalalta = False
print("Gondoltam egy számra 1 és 100 között.")
while tippek < max_tipp and not eltalalta:
tipp = int(input(f"{tippek + 1}. tipp: "))
tippek += 1
if tipp == gondolt:
eltalalta = True
elif tipp < gondolt:
print("A gondolt szám nagyobb.")
else:
print("A gondolt szám kisebb.")
if eltalalta:
print(f"Eltaláltad {tippek} tippből!")
else:
print(f"Elfogytak a tippek. A szám {gondolt} volt.")
A ciklusnak két kilépési oka lehet: elfogytak a tippek, vagy eltalálta. Az eltalalta logikai változó (más néven jelző) őrzi meg, melyik történt – a ciklus után ennek alapján írjuk ki az eredményt. Ha ügyesen felezed a tartományt (50, 25 vagy 75, …), 7 tipp mindig elég – miért?
Miért elég 7 tipp?
Minden jól választott tipp (a még lehetséges tartomány közepe) legalább a felére szűkíti a lehetőségeket. 7 felezés után 100 lehetőségből legfeljebb 1 marad, mert 27 = 128 ≥ 100. Ezt az eljárást bináris keresésnek nevezzük.
9. fejezet
Gyakorló feladatok
Szorzótábla
Kérj be egy egész számot, és írd ki for ciklussal a szorzótábláját 1-től 10-ig:
Szám: 7
1 * 7 = 7
2 * 7 = 14
…
10 * 7 = 70
szam = int(input("Szám: "))
for i in range(1, 11):
print(f"{i} * {szam} = {i * szam}")
Tipp
for i in range(1, 11): – a 11 kell, hogy a 10 is benne legyen.
Páros számok egy sorban
Kérj be egy pozitív egész számot (határ), és írd ki egy sorban, szóközzel elválasztva a 2 és a határ közötti páros számokat (a határt is, ha páros):
Határ: 10
2 4 6 8 10
hatar = int(input("Határ: "))
for szam in range(2, hatar + 1, 2):
print(szam, end=" ")
print()
Tipp
Kettesével lépő range: range(2, hatar + 1, 2). Egy sorba íráshoz: print(szam, end=" "), a végén pedig egy üres print() zárja a sort. (A sor végi szóköz nem számít hibának.)
1-től n-ig
Kérj be egy pozitív egész n-t, és írd ki ciklussal az 1 + 2 + … + n összeget, valamint a négyzetszámok összegét (1² + 2² + … + n²):
n = 100
Összeg: 5050
Négyzetösszeg: 338350
n = int(input("n = "))
osszeg = 0
negyzetosszeg = 0
for i in range(1, n + 1):
osszeg += i
negyzetosszeg += i * i
print("Összeg:", osszeg)
print("Négyzetösszeg:", negyzetosszeg)
Tipp
Két gyűjtőváltozó kell, mindkettő 0-ról indul a ciklus előtt. Ellenőrzésnek: Gauss képlete szerint az összeg n·(n+1)/2.
Számjegyek összege
Kérj be egy tetszőleges hosszú, nemnegatív egész számot, és írd ki a számjegyei összegét. Szövegművelet nélkül, while ciklussal, % és // segítségével dolgozz.
Szám: 90817
A számjegyek összege: 25
szam = int(input("Szám: "))
osszeg = 0
while szam > 0:
osszeg += szam % 10
szam //= 10
print("A számjegyek összege:", osszeg)
Tipp
A szam % 10 az utolsó számjegy; a szam //= 10 levágja azt. Ismételd, amíg a szám nagyobb 0-nál. Kövesd lépésenként a mintamegoldást.
Jegyek átlaga végjelig
Olvass be érdemjegyeket, amíg a felhasználó 0-t nem ír be. A végén írd ki a jegyek számát és az átlagot két tizedesjegyre. Ha egyetlen jegy sem volt, ezt írd ki: Nem adtál meg jegyet.
Jegy (0 = vége): 4 Jegy (0 = vége): 5 Jegy (0 = vége): 3 Jegy (0 = vége): 0 3 jegy, átlag: 4.00
osszeg = 0
db = 0
jegy = int(input("Jegy (0 = vége): "))
while jegy != 0:
osszeg += jegy
db += 1
jegy = int(input("Jegy (0 = vége): "))
if db == 0:
print("Nem adtál meg jegyet.")
else:
print(f"{db} jegy, átlag: {osszeg / db:.2f}")
Tipp
Végjelig olvasás: egy beolvasás a ciklus előtt, egy a mag végén. A 0 jegy esetét a ciklus után kell kezelni, mert 0-val nem lehet osztani.
Számháromszög
Kérj be egy pozitív egész számot (n), és rajzolj n soros számháromszöget: az i-edik sorban 1-től i-ig állnak a számok, szóközzel elválasztva.
n = 4
1
1 2
1 2 3
1 2 3 4
n = int(input("n = "))
for sor in range(1, n + 1):
for szam in range(1, sor + 1):
print(szam, end=" ")
print()
Tipp
Két egymásba ágyazott ciklus: a külső a sorokat számolja (sor 1-től n-ig), a belső az adott sor számait írja ki (1-től sor-ig). A belső ciklus után print() kezd új sort. A sorvégi szóköz nem számít hibának.
Prímszám-e?
Kérj be egy egész számot (legalább 1), és döntsd el, hogy prímszám-e. Prímszám az a 2-nél nem kisebb szám, amelynek csak két osztója van: 1 és önmaga.
Szám: 97
97 prímszám.
Különben: 91 nem prímszám. (Az 1 sem prímszám.)
szam = int(input("Szám: "))
prim = szam >= 2
oszto = 2
while oszto * oszto <= szam and prim:
if szam % oszto == 0:
prim = False
oszto += 1
if prim:
print(f"{szam} prímszám.")
else:
print(f"{szam} nem prímszám.")
Tipp
Próbáld végig az osztókat 2-től. Ha valamelyik osztja a számot, az nem prím (állíts egy jelzőt False-ra, vagy lépj ki break-kel). Elég a szám négyzetgyökéig keresni: ha oszto * oszto > szam, nagyobb osztópár már nem lehet. Az 1-et külön kell kezelni.
Ellenőrzött bevitel
Kérj be egy érdemjegyet (1–5). Ha a beírt szám nem 1 és 5 közé esik, írd ki: Hibás érték., és kérd újra – egészen addig, amíg jó értéket nem kapsz. A végén írd ki: Rögzítve: 4.
Jegy: 7 Hibás érték. Jegy: 0 Hibás érték. Jegy: 4 Rögzítve: 4
while True:
jegy = int(input("Jegy: "))
if 1 <= jegy <= 5:
break
print("Hibás érték.")
print("Rögzítve:", jegy)
Tipp
A while True + break minta (6. fejezet): a ciklusban beolvasol, és ha az érték jó, break-kel kilépsz; különben kiírod a hibaüzenetet, és a ciklus újrakezdődik. (Megoldható while jegy < 1 or jegy > 5: feltétellel is.)
Fizz-Buzz
A klasszikus programozói feladat: kérj be egy pozitív egész n-t, és írd ki a számokat 1-től n-ig, mindegyiket külön sorba – de a 3-mal osztható számok helyett Fizz, az 5-tel oszthatók helyett Buzz, a mindkettővel oszthatók helyett FizzBuzz álljon.
n = 15
1
2
Fizz
4
Buzz
…
14
FizzBuzz
n = int(input("n = "))
for i in range(1, n + 1):
if i % 15 == 0:
print("FizzBuzz")
elif i % 3 == 0:
print("Fizz")
elif i % 5 == 0:
print("Buzz")
else:
print(i)
Tipp
Ugyanaz a csapda, mint a 2. modul oszthatósági feladatában: a „mindkettővel osztható” esetet kell először vizsgálni.
10. fejezet
Összefoglalás
| Eszköz | Lényeg |
|---|---|
for x in sorozat: | a sorozat minden elemére lefut; x körönként a következő elem |
range(start, stop, step) | számsorozat; a stop már nem része; range(n) = 0…n−1 |
while feltétel: | amíg a feltétel igaz; minden kör előtt újra kiértékeli |
| összegzés, számlálás | gyűjtőváltozó a ciklus előtt 0, a magban += |
| szélsőérték | kezdőérték az első elem; nagyobbat találva csere |
break, continue | kilépés a ciklusból / ugrás a következő körre |
| beágyazott ciklus | a belső ciklus a külső minden körében végigfut |
Gyakorold tovább: írj programot, amely bekéri egy osztály dolgozatainak pontszámait végjelig (−1), és kiírja a legjobb és a leggyengébb pontszámot, az átlagot, valamint hogy hányan értek el legalább 50 pontot. Előbb gondold végig: hány gyűjtő- és számlálóváltozó kell, és mi legyen a kezdőértékük?