1. Computer Science

A számítási folyamatok

  • A számítógépben: számítási folyamatok
  • Ezek adatokat manipulálnak
  • A működésüket programok vezérlik
Varázsló

Milyenek?

  • Nem láthatóak, nem foghatóak meg – de igaziak
  • Értelmes munkát végeznek, kérdésekre válaszolnak, pénzt mozgatnak bankok között, járműveket vezetnek

2. A félév végére…


Telefonkönyv

Kit keresünk? Tapsi Hapsi

Száma: 555-125687

Új keresés (i/n)? n_

Hogyan lehet olyan programot írni, amely sok adatot tárol és dolgoz fel?

Táblázatkezelő

Megváltoztatunk egy cellát a táblázatkezelőben, és újraszámolódik minden, ami kell. Hogyan lehet ezt megcsinálni?


Kukacos játék

Egyszerű játékok: hogyan működik például egy kukacos játék? Hogyan jegyzi meg, merre halad a kukac?

Amőba játék

Amőba játék: mitől tűnik úgy a gép, mintha intelligens lenne? Meg tudod verni a saját amőba játékodat? Meg tudja verni a szobatársad? Meg tudod úgy erősíteni, hogy már ne tudja?! :)

3. Tudnivalók I.

Honlap, adminisztrációs portál

Az információ hiteles forrása: https://infopy.eet.bme.hu/


Konzultáció: kérdések, nagy házi stb.

Saját laborvezetők! A portálon lehet üzenetet írni.


Oktatás: kétféle óra

  • Előadás: ez most itt
  • Labor: géptermi órák – önálló munka, programozás
  • Labor átjelentkezés: első két héten, fogadó oktató beleegyezésével
  • Labormunka feltöltése

Az előadásokra épülnek a laborok. Ezt figyelembe véve készült a tematika is. Ezért lesz az jellemző a félévben, hogy a laborokon vett feladatok régebbi, egy-két héttel előbbi előadásanyaghoz kötődnek. A laborokra készülve, az előadásanyagot megértve érdemes menni, különben haszontalan az ott töltött idő.

A labor órákhoz fognak kötődni a kis ZH-k és a nagy házi feladat is. A laborokon az egyik oktatótok feladata lesz a kis ZH-k javítása, a másik a nagy házi feladat konzultálása és értékelése – de természetesen bármelyik laborvezetőt megkereshetitek a kérdéseitekkel!

4. Tudnivalók II.

Számonkérések a félév közben

  • Részvétel: jelenlét előadáson és laboron
  • Beugró: laboron nyújtott teljesítmény
  • KZH: kisebb feladatok, 20–25 soros programok írása papíron
  • NZH: kb. 4–5× KZH
  • NHF: egyénileg írt program dokumentációval
  • Szorgalmik: megajánlott jegy szerezhető

Vizsgaidőszakban

  • Vizsga a teljes anyagból; jegy a vizsgadolgozat és NHF alapján
  • Megajánlott jegy, nem kell vizsgázni, ha jó ZH-k + szorgalmik

Algoritmusok

6. A tudás fajtái

Amikor a tudást, ismeretanyagokat szeretnénk csoportosítani, azt megtehetjük annak „deklaratív” vagy „imperatív” jellege szerint.

Deklaratív tudás

  • „Mi az, ami igaz?”
  • Állításokat tesz

Imperatív tudás

  • „Hogyan kell csinálni?”
  • Módszereket ad

Példa: egy szám négyzetgyöke

x gyöke egy olyan y,
amire y2=x,
és y≥0

Deklaratív tudás: egy számról meg tudjuk mondani, hogy egy másik négyzetgyöke-e.

Tippeljük meg, mennyi: y'.
A tipp javítható: (y'+x/y')/2
Javítgassuk, amíg nem elég jó.

Imperatív tudás: meg tudjuk vele határozni egy tetszőleges szám gyökét.

Az imperatív tudás sokszor hasznosabb. A deklaratív tudás alapján, ha adott egy y, akkor meg tudjuk mondani, hogy az egy szintén adott x-nek gyöke-e. De többet nem tudunk mondani. Ennél sokkal jobb az, ha kapunk egy x-et, és meg tudjuk határozni a hozzá tartozó y-t!

Az imperatív programozási paradigma lényege: olyan programot kell írnunk, amelyben lépésről lépésre megmondjuk a számítógépnek, hogy mikor mi a teendő. A hangsúly az imperatív nyelvekben a megoldás módján van. Ebben a félévben ezt a gondolkodásmódot kell megtanulni.

Léteznek deklaratív programozási nyelvek is, amelynél megadjuk, milyenek a helyes megoldások, és a számítógép találja ki a megoldás módját. Ezekkel könnyebb lehet programozni, de a megoldható problémák köre sokkal szűkebb, mint az imperatív nyelvek esetében. Deklaratív programozási nyelv például az adatbázisoknál használt SQL: ebben megadhatjuk, mely adatokra van szükségünk, és a program találja ki, hogyan kell kikeresni azokat az adatbázisból.

7. Specifikáció és algoritmus

A programozásban általában kapunk egy feladatot – egy feladatot pontosan leíró specifikációt. Ez legtöbbször deklaratívan adott. Nekünk kell kitalálni a hozzá tartozó imperatív megoldást, azaz egy módszert, amellyel a bemenetből a kimenet előállítható.

Specifikáció: mit kell csináljon

  • Mi lesz a bemenete, mi a kimenete, mi ezek között az összefüggés
  • Ez általában deklaratívan adott

Különféle gépek
Gépek bemenettel
és kimenettel

Algoritmus: hogyan csinálja

  • A megoldás „lépésről lépésre” leírása: imperatív módon
  • Ezt nekünk kell kitalálni.
    Nincs rá általános módszer.

Művészet? Tudomány? Mérnöki feladat?

Nincs olyan általános módszer, amely segítségével egy algoritmus szisztematikusan kidolgozható lenne. Vagyis amellyel egy deklaratívan („mi igaz”) adott problémára imperatív („hogyan kell csinálni”) megoldás lenne adható. Hogy ez vajon művészet, tudomány vagy mérnöki feladat, azt nem lehet 100%-osan eldönteni:

  • Egyrészről tudomány, ahogyan azt az angol neve is mutatja: computer science. Az algoritmusok kezelhetőek matematikailag. Helyességük bizonyítható, tulajdonságaik (pl. időigény) számszerűsíthetőek.
  • Másrészről művészet, hiszen a kidolgozásuk gyakran ötletelésen, felismeréseken múlik. Az egyik leghíresebb programozásról szóló könyv „A számítógépprogramozás művészete” című sorozat (Donald Knuth: The Art of Computer Programming). A címe mindent elmond.
  • Harmadrészt mérnöki feladat, éppen annyira, mint egy autót megtervezni. Figyelni kell arra, hogy a részegységek ne zavarják egymást. Irányítani kell a csapatok munkáját, méghozzá úgy, hogy egymástól függetlenül is tudjanak dolgozni. Vannak szabványok, amelyeket követni kell.

A programozás során rengeteg olyan problémával találkozunk, amelyek rendszeresen felmerülnek. Vannak jól bevált megoldások, amelyeket érdemes újra és újra felhasználni. Egy jó programozó bármikor tud mondani többféle módszert is arra, hogyan lehet egy névsort ábécébe rendezni, sőt azt is tudja, mikor melyik módszer a gyorsabb. Ezért sokszor, amikor programozunk, már megtanult algoritmusokat kódolunk csak le.

8. Algoritmus – definíció

Algoritmus

Módszer a feladat megoldására.

  • Utasítássorozat megengedett lépésekből
  • Mechanikusan végrehajtható
  • Véges sok lépésből áll
  • Mindig egyértelműen adott a következő lépés
  • Minden időpontban véges sok memória kell

A papíron összeadás és a prímtényezős felbontás olyan algoritmusok, amelyeket általános iskolában tanítanak. Vegyük észre, hogy mind kimerítik a fenti feltételeket: mechanikusan végrehajthatóak, mindig pontosan definiálják a következő lépést – és valamilyen bonyolult probléma megoldását adják meg úgy, hogy közben egyszerű lépéseket használnak.

 175
+343
────
 518
összeadás
  • „az összes számjegyet”
  • „add össze”
  • ha eléri a 10-et, van átvitel”
20│2
10│2
 5│5
 1│ 
prímtényezős felbontás
  • amíg nagyobb, mint 1”
  • ha osztható”
  • „írd le az osztót”

9. Pszeudokód: egy algoritmus leírása

A programozásban a módszerek, algoritmusok szöveges leírását adjuk meg.

Ez egy
algoritmus

Kérj egy számot a felhasználótól, legyen ez N.
A értéke legyen 1.
Ellenőrzés: Ha N=1, ugorj előre a „vége” címkéhez.
Legyen A értéke mostantól A·N.
N értékét csökkentsd 1-gyel.
Ugorj vissza az „ellenőrzés” címkéhez.
Vége: Írd ki A értékét.


A szöveges leírás (pszeudokód) tartalmazza:

  • A megjegyzett számok listáját: ezek a változók.
  • Az elvégzett műveleteket: szorzás, csökkentés.
  • A lépések sorrendjét meghatározó utasításokat és döntési pontokat: a vezérlést.

Ezzel megadjuk az algoritmust. Vegyük észre, hogy teljesen mechanikusan végrehajtható lépésekről van szó: egyszerű, matematikai jellegű lépéseket végzünk. Szorzást kell elvégezni, egyenlőséget vizsgálni stb.

Próbáld is ki az algoritmust, számítsd ki a 4 faktoriálisát az utasításokat követve! Jegyezd föl papírra az A és az N értékét; ha azt kéri az algoritmust, hogy módosítsd, akkor radírozd ki, és írd a jegyzeteidhez az új számot.

10. A programok

A programkódok

  • Számítógép által érthető programozási nyelveken
  • A nyelv elemeit meg kell tanulni: szótár: szavak, amelyekkel fogalmazunk, szintaxis: a nyelvtani szabályok
# legnagyobb közös osztó
a = int(input("a? "))
b = int(input("b? "))

while b != 0:
    t = b
    b = a % b
    a = t

print("lnko =", a)

Mint mikor angolul vagy németül tanulunk: a számítógép nyelvének elemeit meg kell tanulni.


Programozási nyelv

Python logo
  • A Python nyelvet fogjuk használni (3.0: Guido van Rossum, 2008.)
  • Egyike azon nyelveknek, amit elsőként tanítanak

A Python nyelvet eredetileg Guido van Rossum fejlesztette ki, 1991-ben jelent meg először. Azóta több szabványosított változata lett. A jelenlegi változata a 3.0-s verzió, amely 2008-ben jelent meg. (Gyakran használják még a 2.0-sat is, de azt 2020-ban végleg nyugdíjazni fogják.)

A programozás alapjai

12. Helló, világ

A tradicionális első program forráskódja:

első Python
programunk
# üdvözlet
print("Helló, világ!")

Helló, világ!

A „helló, világ” programoknak nagy hagyománya van. Ez már a '70-es évek óta így van, a legtöbb programozás tankönyv ezzel kezdődik.

print() – kiírás

  • print(): kiír valamit
  • "szöveg": a szöveg (sztring, karaktersorozat) idézőjelben. A gép nem keres benne értelmet
  • A print()-nek adott szöveget, ún. paramétert zárójelbe (parenthesis) kell tenni

# üdvözlet – megjegyzések

  • #: megjegyzés (comment)
  • A gép nem foglalkozik vele, magunknak írjuk
  • Magyarázatot írhatunk benne arról, hogyan működik a programunk

Szerencsére nekünk azzal nem kell foglalkoznunk, pontosan hogyan fogja a gép megjeleníteni a szöveget (megrajzolni a betűket). A print() függvényt készen kapjuk, bármelyik programunkban használhatjuk.

13. Számológép

# Számológép
print("Eredmény:", 2*3)

A print() nem csak egy dolgot tud kiírni, hanem akár többet is. A kiírandó dolgokat vesszővel elválasztva adjuk meg, amiket a print szóközzel elválasztva ir ki. És nem csak egyszerű szöveget, hanem számokat is. A fenti példában kiíródik majd az „Eredmény:” szöveg, utána egy szóköz, végül pedig a szorzat.

A kiírt szám jelen esetben ez egy egész számokkal végzett művelet. A program egy nagyon egyszerű számológép: a 2*3 helyére bármilyen matematikai kifejezést beírhatunk, és a program futtatása után megkapjuk az eredményt. A szokásos módon használhatjuk a négy alapműveletet és a zárójelezést is. Természetesen a Python nyelvtani szabályaira figyelni kell, például a szorzás jele a *, nem a ·.

14. A típusok fogalma

Hogy beszélni tudjunk róla, hogyan dolgoznak fel a programok adatokat, meg kell ismernünk a típus fogalmát.

Típus

Az értékkészlet és a műveletek együttese.

  • A változóknak is van típusa – ez adja meg az értékkészletet és a végezhető műveleteket is.
  • A típusok szinte minden programozási nyelvben megtalálhatóak.

Típusok: példák
típusértékkészletműveletek
egész-1, 2, 5, …összeadás, kivonás, összehasonlítás
valós1.5, 7, 3.14, …összeadás, kivonás, összehasonlítás
logikaiigaz, hamisés, vagy, tagadás
karakterbetűk, írásjelek, …összehasonlítás, következő, előző
szövegkaraktersorozatokösszefűzés, keresés

15. Kifejezések

A kifejezések a programjaink legalapvetőbb építőkövei: műveleteket végeznek el. Ezeket ismerjük a matematikából is: összeadás, kivonást stb., de a programozásban sokkal többféle lesz.

Kifejezések és típusok

műveletek
kifejezésérték
1+23
5+2*311
6*(3+4)42
vegyes kifejezések
kifejezésérték
1<2igaz
2≥3hamis
"a" < "b"igaz
hibás kifejezések
kifejezéshiba
3*(1+vége?
1-HAMIStípus!
1+"alma"típus!

A műveletek adott típusokon végezhetőek el, és az eredménynek is van valamilyen típusa. Ezek azonban nem feltétlenül ugyanazok. Például egy szám+szám művelet eredménye is szám, de egy szám<szám összehasonlítás logikai, igaz/hamis típusú eredményt ad. Lehetséges az is, hogy egy művelet két operandusának típusa sem egyezik meg: időpont+időtartam→időpont. Pl. 12:15+30 perc=12:45.


A kifejezésekről

  • Meg kell feleljenek a nyelvtani szabályoknak
  • Fontos a típus, hogy értelme legyen egy kifejezésnek!
    • Ha X szám, X+3 értelmes.
    • Ha X szöveg, X+3 értelmetlen.

A kifejezés értelmességéhez, helyességéhez szükséges az is, hogy az egyes műveleti jelek (operátorok) mellett megfelelő típusú operandusok legyenek. Az 1-HAMIS kifejezés hiába tűnik helyesnek nyelvtanilag (a mínusz jel mindkét oldalán egy érték van), mégis értelmetlen, mert egy egész számból nem lehet kivonni egy logikai értéket. Ugyanígy értelmetlen az 1+"alma" kifejezés is.

16. A változók és használatuk

Mi az a változó?

Egy eltárolt, megjegyzett érték, amelynek nevet adunk.

  • Egy változó egy dolgot jegyez meg, ezért minden megjegyzett dologhoz külön változó kell.
  • A programnak időbeliséget adnak: miattuk számít a műveletek sorrendje!

X értéke legyen 5.     értékadás (írás)

Leírom X-et.           kiértékelés (olvasás): „5”

X értéke legyen X+1.   kifejezés kiértékelése, aztán értékadás

Leírom X-et.           ez „6” lesz

Mit lehet csinálni egy változóval?

A változókban tároljuk a programunk által megjegyzett adatokat, részeredményeket.

Kiértékelés
Egy változóban tárolt adatot előveszünk, „olvassuk”.
Értékadás
Egy változóban új adatot jegyzünk meg, „írjuk”. A régi értéke ilyenkor elveszik!

A program futása során, egyes időpontokban más lehet az értékük: ugyanaz a művelet más eredményt adhat egy másik pillanatban. Emiatt fontossá válik a műveletek sorrendje. Fontos gondolat, hogy ez az értékadás miatt van. Ha nem létezne értékadás, akkor ez nem lenne így. Például az alábbi képletben teljesen mindegy, hogy melyik tényező értékét számítjuk ki előbb: (3+4)×(6-9)×(12-4-6+5). Haladhatunk balról jobbra, jobbról balra, vagy akár kezdhetjük a középső 6-9-cel is. Ezzel szemben a fenti programkódban láthatóan számít az, hogy a növelés előtt vagy után írjuk le az X változó értékét. A faktoriálist számító gépnél is számított az, hogy milyen sorrendben nyomjuk meg a gombokat.

17. Változók a Python nyelvben

Definíció (létrehozás)

x = 2         # x egész

s = "almafa"  # s szöveg

Változót úgy hozunk létre, hogy értéket adunk neki.

  • A változóinknak nevet adunk, ezeknek betűvel kell kezdődniük. Lehet ékezetes is, de nem szokás.
  • Ezzel megmondjuk a gépnek a változó típusát is: amilyen értéket adtunk neki.
  • A fenti példában x egész típusú változó, s pedig szöveg (string) lesz.

Használat

x = 3      # x legyen 3

x = x + 1  # x nőjön eggyel

Értékadás: x elfelejti régi értékét, és mostantól ezt tárolja.

  • = az értékadás művelet jele
  • x = x+1: nem egyenlet, hanem értékadás
  • „x legyen egyenlő x pillanatnyi értéke +1-gyel”

Valójában itt az x változóval két műveletet is végzünk: egyrészt kiolvassuk (megnézzük a régi értékét), aztán pedig írjuk (módosítjuk) is.


Kiírás

x = 2 * 3

print("Értéke:", x)
Értéke: 6
  • A print() változót is kaphat.
  • Valójában nem tudja, változót kapott-e, hanem csak a kiolvasott értéket kapja meg.

Beolvasás

nev = input("Hogy hívnak? ")

print("Szia,", nev)
Hogy hívnak? _
  • input(): szöveg beolvasása.
  • A paraméter a kérdés (elmaradhat).
  • A beolvasott szöveget értékadással tesszük a változóba.

18. A Python nyelv dinamikusan típusos

Vannak statikusan és dinamikusan típusos programozási nyelvek. A Python nyelv dinamikusan típusos.


Ez azt jelenti, hogy a változóknak nem kell előre megadni a típusát, sőt egy adott nevű változó típusa is változhat a program futása közben.

x = 12
print("Értéke:", x)  # Értéke: 12

x = "alma"
print("Értéke:", x)  # Értéke: alma

Általában viszont egy változóval ilyet nem szoktunk csinálni. A változónak a programban meghatározott szerepe, célja van, ami alapján nevet is adtunk neki. A szerepéből pedig következik a típusa is; egy ember neve sosem lesz egész szám, a kör sugara pedig nem lesz szöveg. Emiatt valószínűleg nem logikus az a program, ahol egy egész típusú változó egyszercsak szöveggé változik.

A statikusan típusos nyelvekben a fentiek ellenkezője igaz. Ott a programkódban meg kell adnunk előre minden egyes változó típusát, és az a típus nem változhat a program futása alatt.

19. Sztringek összefűzése

Feladat: írjunk programot, amelyik nevén üdvözli a felhasználót!

Hogy hívnak? Pistike

Szia, Pistike!

Ne legyen szóköz a név és a felkiáltójel között!


Ez az első interaktív programunk, amely nem csak kiír valamit, hanem kérdez is a felhasználótól – sőt az eredmény a felhasználó által adott bemenő adattól függ.

Az eddigiek alapján ehhez szükségünk lesz egy változóra. Előbb beolvassuk a nevet egy input() segítségével, utána pedig kiírjuk az üzenetet a print()-tel.

nev = input("Hogy hívnak? ")
print("Szia, " + nev + "!")     # egy paramétere van!

+ operátor sztringek között: összefűzés, konkatenálás (concatenation).

Ha a print("Szia,", nev, "!") sort írnánk, akkor Szia, Pistike ! lenne az eredmény, vagyis a felkiáltójel előtt zavaróan egy szóköz lenne még. Ezt a megoldásban úgy kerüljük el, hogy egyetlen egy sztringet állítunk elő, amelyben összefűzzük a + operátorral (művelettel) a három sztringet, a Szia köszönést, a nevet és a felkiáltójelet. Az összefűzésnél nem kerül szóköz a darabok közé, pl. "alma" + "fa" értéke almafa lesz. Így a felkiáltójel előtt nem lesz szóköz, a vessző után viszont mi tettünk.

Egy sorban?

Csak apró betűs megjegyzésként: valójában a váltózra sincsen szükség. Írhatnánk akár ezt az egy sort is:

print("Szia, " + input("Hogy hívnak? ") + "!")

Ez azonban nem szép stílus, mert nehezebb kibogozni a kódot nézve, hogy mit csinál a program. De működni fog. Hiába van „előbb” a print(), mégis az fog később végrehajtódni. A print() paramétere az összefűzés eredménye; tehát azt előbb elő kell állítania a gépnek, csak utána kaphatja meg az egyetlen egy sztringet a print(). Tehát lehet így írni, de ezt jobb nem erőltetni. Ez a program helyesnek ugyan mondható, de jónak nem.

20. Az operátorok polimorfizmusa

Az operandusok típusától függően eltérő lehet a működés.

Számok esetén összeadás, sztringek esetén összefűzés történik.

print(1 + 2)
print("alma" + "fa")
3
almafa


Típusokkal kapcsolatos hibák

print("alma" + 123)     # hibát dob
Traceback (most recent call last):
  File "proba.py", line 5, in <module>
    print("alma" + 123)
TypeError: must be str, not int

Egy sztring és egy szám nem adható össze, ezért hibát dob a program: TypeError.

21. Konverziók: int(), float() és str()

a = input("a? ")
b = input("b? ")

print("a+b =", a + b)
a? 2
b? 3
a+b = mi lesz itt?

Mi az oka annak, hogy 23 íródott ki? Az, hogy az input() által visszaadott érték sztring típusú. Így sztring lesz a-ban és b-ben is, még akkor is, ha a felhasználó számjegyeket gépelt be. Márpedig sztringeket úgy kell összefűzni, hogy egymás után írjuk a bennük tárolt karaktereket; így lesz "23" (huszonhárom, vagyis valójában kettő-három) az eredmény, nem pedig 5. Ha a felhasználó almát és fát gépel be, akkor nem is tűnik furcsának az eredmény, "almafa".


Mi a teendő, ha mégis a két szám összegét szeretnénk kiírni, 2+3 = 5?

a = input("a? ")
b = input("b? ")

print("a+b =", int(a) + int(b))

A beolvasott sztringeket számmá kell konvertálni.

Konverziók

  • int(s): sztring → egész szám, pl. "123" → 123
  • float(x): sztring → valós szám, pl. "3.14" → 3.14
  • str(x): szám → sztring, pl. 123 → "123"

A konverziók függvényekkel végezhetők el. Például az int() függvény paramétere egy sztring, és visszaadja azt a számot, amit talál benne (tízes számrendszerben). Így a fenti kódban az a és a b változóban tárolt sztringeket értelmezve szám keletkezik, és az összeadás már számokon dolgozik.

Valójában a fenti programot inkább így szoktuk megírni:

a = int(input("a?"))
b = int(input("b?"))

print("a+b =", a+b)

Ez azért jobb, mert a beolvasás helyén már látszik, hogy számokat vár a program.

Ha olyan konverziót szeretnénk elvégezni, ami lehetetlen (pl. int("almafa")), akkor ValueError típusú hibát fogunk kapni. Később majd lesz róla szó, hogy ezeket a hibákat hogyan lehet kezelni.

Vigyázat!

Figyelni kell arra, hogy a konverzió nem a változót módosítja, hanem egy új értéket hoz létre. Tehát önmagában leírni az str(x)-et vagy egy int(s)-t haszontalan:

s = input()

int(s)          # nem csinál semmit, értelmetlen

print(s + "!")  # működik, mert s egy sztring

A konverzió értékét fel kell használni egy kifejezésben, vagy eltárolni másik változóban.

22. A kör kerülete és területe

Feladat: írjunk programot, amely megkérdezi a felhasználót, mekkora egy kör sugara, majd kiírja a kör kerületét és területét!

A megoldás algoritmusa: követjük az események sorrendjét:

  • Megkérdezzük a felhasználót, mekkora a kör.
  • Megvárjuk, amíg válaszol (és megjegyezzük a választ).
  • Kiírjuk a kerületet és a területet.

(Vagy épp másképp is megközelíthetjük: ahhoz, hogy kiírjuk az eredményt, előbb a bemenő adatokra van szükségünk. Anélkül úgysem menne. Az adatok beolvasása előtt pedig feltesszük a kérdést, mert később már nem lenne értelme.)

A kör sugarát a sugar nevű változóban tároljuk. Azért kell eltárolni, mert a billentyűzetről beolvasott értékre a programban több helyen is hivatkozunk: egyrészt akkor, amikor jelezzük, hogy hova kell beolvasni; másrészt a kerület kiszámításakor; harmadrészt a terület kiszámításakor.

A beolvasott sztringet számmá kell alakítanunk. Mivel a sugár lehet valós szám is, ezért ezt a float() konverzióval fogjuk megtenni.

import math

print("Mennyi a kör sugara?")
sugar = float(input())

print("Kerület =", 2 * sugar * math.pi)
print("Terület =", sugar**2 * math.pi)

Mennyi a kör sugara?
4.5
Kerület = 28.274333882308138
Terület = 63.61725123519331

Fontos, hogy mindig érthető nevet adjunk a változónak, amely utal a szerepére. Ez megkönnyíti a programkód olvasását. Itt jó lenne még az r név is, de az xx vagy az a1 már nem igazán. A kiszámított kerületet és területet is tehettük volna egy második és harmadik változóba (pl. K és T néven), de azokat nem akartuk többször használni.

import math

Lássuk, mi az újdonság még a programban! Az egyik az import math sor. Ezzel a matematikai modult tudjuk beemelni a programunkba. Ez rengeteg függvényt tartalmaz, pl. math.sqrt() a négyzetgyök, math.sin() segítségével pedig szög szinuszát tudjuk kiszámítani. De tartalmaz konstansokat is: math.e a természetes logaritmus alapszáma (2,718), amire pedig itt szükségünk volt, az a math.pi, a π értéke (3,1416).

Másik pedig a hatványozás operátor. Ezt Pythonban a ** operátorral érjük el: alap ** kitevő. Ha valakinek jobban tetszik, ez írható függvényként is: math.pow(alap, kitevő). De akár a négyzetgyök helyett is írhatunk feledik hatványt: math.sqrt(2) ugyanannyi, mint 2 ** 0.5, mindkettő értéke 1,414.

pi = 3.1416
a programban
tizedespont,
nem vessző!

Apropó valós számok: a Python programunkba a valós számokat nem tizedesvesszővel, hanem tizedesponttal kell írnunk. A vessző függvényparaméterek elválasztására való!

print(3, 1416)  # két külön szám, 3 és 1416

print(3.1416)   # egy szám, a π közelítő értéke

A vezérlési szerkezetek

24. Az imperatív programok működése

Elemi lépések, műveletek a számítógépen

  • Kiírunk valamit a képernyőre
  • Adatot kérünk a felhasználótól
  • Kiszámítunk valamit
PROGRAM
    KIÍR: "Helló, világ!" egyetlen elemi lépés
PROGRAM VÉGE

A legegyszerűbb program egyetlen elemi lépésből áll, egyetlen tevékenységből. Az egy lépésből megoldható feladatoknál persze szinte mindegyik bonyolultabb. Ha több lépésünk van, meg kell mondanunk, milyen sorrendben szeretnénk azokat a lépéseket elvégezni.


Mit csinál a program?

  • A program kifejezésekkel kiszámol értékeket
  • Ezeket eltárolhatja változókba vagy kiírhatja a kimenetére
  • A számítások sorrendjét a vezérlési szerkezetek adják meg
3211 │ 13
 247 │ 13
  19 │ 19
   1 │   

Például egy prímtényezős felbontás algoritmusában nem mondhatjuk azt, hogy „oszd el a számot a legkisebb prímszámmal”. Legalábbis amíg nem mondtuk meg azt, nem raktuk össze kiértékelésekből és értékadásokból, hogy hogyan lehet megkeresni a legkisebb prímszámot, ami osztja a bal oldalit.

25. Szekvencia: egymás utáni lépések

Folyamatábra

Szekvencia folyamatábrán

Program

   print("Oldalhossz?")   
   a = int(input())   
   t = a*a   
   print("Terület =", t)   

Működés

a: 
t: 

A programok vezérlési szerkezetét grafikusan is megadhatjuk. A folyamatábra (flow chart) és a struktogram ennek két elterjedt módja. A folyamatábrán a nyilak mutatják a lépések sorrendjét.

Mire használjuk itt a változót? Arra, hogy megjegyezzük a felhasználótól származó értéket – és később a négyzetét.

26. Elágazás: feltételes végrehajtás

Feladat: Írjunk programot, amely kér egy számot a felhasználótól.
Mondja meg, hogy páros-e vagy nem.

A programsorok végrehajtása feltételhez (igazságértékhez) köthető.

Folyamatábra

Elágazás folyamatábrán

Program

   szam = int(input())   
   if szam % 2 == 0:   
       print("páros")       ha igen
   else:
       print("páratlan")    ha nem

Működés

szam: 





==
egyenlő-e
%
maradék

A szám/2 maradékának vizsgálata után a program végrehajtása az elágazás igaz vagy hamis ágában folytatódik. Így a kettő közül mindig csak az egyik felirat íródik ki.

Szintaxis és fogalmak

if feltétel:   utána kettőspont
    utasítás
else:          opcionális
    utasítás
Elágazás (conditional)
Az egész vezérlési szerkezet, amelyben egy bizonyos programrészlet végrehajtását feltételhez köthetjük.
Feltétel (condition, predicate)
A logikai kifejezés, amelynek igaz/hamis voltától függ, hogy végrehajtódik-e az adott programrészlet. Ez egy ún. igazságértékre alapozott választás.
Igaz ág, következmény (consequent)
Az a programrészlet, amely akkor hajtódik végre, ha a feltétel igaz volt.
Hamis ág, „else” ág (alternative)
Ez akkor hajtódik végre, ha a feltétel hamis volt.

Figyeljünk meg két dolgot a fenti kód szintaktikáján, azaz a Python nyelvtani szabályain! Egyik az, hogy az elágazás feltétele után kettőspontot kell tenni. Másik pedig az, hogy azokat az utasításokat, amelyek a feltétel igaz ágában és hamis ágában vannak, bentebb kell szedni, azaz indentálni kell. Hogy ezt hogyan tesszük, az ízlés kérdése: lehet két szóköz vagy négy szóköz, esetleg tabulátort is használhatunk. Ami nagyon fontos: legyünk konzisztensek, legyen az egész programunk mindenhol egyformán indentálva! Ha nagyon elrontjuk, akkor IndentationError típusú hibajelzés a jutalmunk a géptől.

Ebben a tárgyban mi mindenhol szóközöket fogunk használni az indentáláshoz. A Python közösség egy útmutatóban ugyanezt javasolja, és legtöbben ezt használják: PEP 8 – Style Guide for Python Code. (Aki nagyon szembe megy a világgal, arról leginkább azt szokták gondolni, hogy nem ért a programozáshoz...)

27. Számok 1-től 10-ig

Feladat: írjunk programot, amelyik kiírja a számokat 1-től 10-ig.

sorminta
:-(
KIÍR: 1
KIÍR: 2
KIÍR: 3
…
KIÍR: 8
KIÍR: 9
KIÍR: 10

Probléma

  • Egyrészt: kipontozás? Ez nem szép megoldás.
  • Másrészt: mi van akkor, ha a felhasználó kellene megmondja, meddig kellenek a számok? A program forráskódja nem függhet a bemenetétől!

Sorminták – máshol tök jó, programozásban ne
A programozásban inkább ne!

28. Ciklus: működés

Ciklus (loop): programrész ismétlése, amíg egy feltétel fennáll.

Folyamatábra

Ciklus folyamatábrán

Program

   print("Meddig írjam ki?")   
   n = int(input())   

   x = 1   
   while x <= n:   
       print(x, end=" ")   
       x = x+1   

   print(".")   

Működés



n: 
x: 

Fogalmak

elöltesztelő
ciklus
while feltétel:
    utasítás
Ciklusmag, ciklustörzs (loop body)
Az ismételt utasítás(ok). Itt a print(x) és az x = x+1. Ha a ciklustörzsben több utasítás is van, az egy szekvencia, ami Pythonban egyszerűen úgy jelenik meg, hogy egymás alá több utasítást tettünk. Ezért fontos az egységes indentálás: amíg bentebb van a következő sor, addig a ciklus részének fogja azt a gép tekinteni. Az utolsó, pontot kiíró sor már nem része a ciklusnak.
Ciklusfeltétel (loop condition)
A kifejezés igaz/hamis értéke alapján eldől, hogy végrehajtódik-e a ciklus törzse. Itt az x <= meddig.
Elöltesztelő ciklus (pre-test loop)
A feltételt a ciklustörzsbe lépés előtt ellenőrizzük.
Iteráció (iteration)
A ciklustörzs egy végrehajtása a program futása közben.
Ciklusváltozó, iterátor (iterator)
A ciklust vezérlő változó, ha van ilyen (ebben a példában az X).

Itt mire jó a változó? Azzal tudjuk elérni azt, hogy a ciklus törzsében lévő kiírás utasítás mindig más számot írjon a képernyőre! Azzal számoljuk, hogy éppen hol tartunk.

A print() utasításnál láthatunk egy újdonságot is: az end=" " elnevezett paraméter segítéségvel azt adjuk meg a print()-nek, hogy a kiírt dolgok után ne egy újsort kezdjen, hanem mást írjon ki. Jelen esetben egy szóközt tettünk, így az egymás utáni számok közé, bár külön print() írta ki őket, szóköz kerül.

A neves paraméterek megadásánál az = két oldalára nem szokás szóközt tenni, tehát end=" "-t írunk, nem pedig end = " "-t. Így a szemünk meg tudja ezt különböztetni az értékadástól. Ezek apró szabályok, amiket nem lehet egyszerre mind megjegyezni, de könnyen hozzá lehet szokni. A tárgy anyagában egész félévben követni fogjuk ezeket a szabályokat.

29. Ciklusok: további tudnivalók

Egy ciklus folyamatábrája

Ciklusfeltételek

  • A ciklus bennmaradási feltétele logikai kifejezés
  • Újra és újra kiértékelődik minden iterációban
  • Ha teljesül, végrehajtódik a törzs, ha nem, a ciklus után folytatódik a program

Hányszor hajtódnak végre?

  • Ahányszor a feltétel teljesül
  • Ez lehet 0 is: a törzs egyszer sem hajtódik végre
  • A feltétel előbb-utóbb hamissá kell váljon, különben végtelen ciklus (infinite loop) keletkezik

A feltétel hamissá kell váljon előbb-utóbb: praktikusan ez azt is jelenti, hogy a ciklusváltozónak, ha van, az egyes iterációk között változnia kell. Különben ugyanaz marad az értéke, és a ciklus feltételének igazságértéke sem fog változni! Ha nincs olyan utasítás a ciklusban, amely a ciklusváltozó értékét változtatja, az gyanús.

30. Ciklusszervezés: olvashatóság!

Számok kiírása 1-től 10-ig:

jól megírt
i = 1
while i <= 10:
    print(i)
    i = i+1
rossz, követhetetlen
i = 0   # :(
while i <= 9:   # :(
    i = i+1
    print(i)    # :(

Ha áttekinthetően szeretnénk ciklust írni, akkor érdemes az első sémát megtartani. Az ismérvek:

  • A ciklus előtt közvetlenül a ciklusváltozó inicializálása szerepel. Ez lesz az első iterációban az értéke, tehát ez az első feldolgozott elem. Ezt ne máshova tegyük, ne messzebbre: közvetlenül elé.
  • A ciklustörzsben elöl a teendők szerepelnek. Mivel ez elöl van, ezért a ciklusváltozó értéke az első iterációban éppen a cikluson kívül beállított érték, vagyis az első elem! (Különben a ciklusváltozót olyan értékre kellene inicializálni, amit aztán nem dolgozunk fel, ahogyan az a jobb oldalon is látszik.)
  • A ciklustörzs végén az utasítás, amely lép a következő elemre. Ez változtatja a ciklusváltozót. Utána már nem írunk semmit, hiszen akkor egy iteráción belül némely utasítások még a régi, némelyek pedig már az új értékére vonatkoznának.
Ez még jobban látszik egymásba ágyazott ciklusok esetében. Ha ott rossz helyen szerepelnek a kezdeti értékek, akkor váratlan helyeken kezdenek el feleslegesnek látszó értékadások feltűnni. A megoldás erre ugyanaz, mint a fenti esetben: a ciklusok elé kell tenni a hozzájuk tartozó kezdeti értékeket.
Ne így...
x = 1          # mit keres ez itt :(
y = 1
while y <= 5:
    while x <= 5:
        print(x*y, end="\t")
        x = x+1
    print()
    x = 1      # mit keres ez itt :(
    y = y+1
Hanem inkább így!
y = 1
while y <= 5:
    x = 1      # itt a helye! :)
    while x <= 5:
        print(x*y, end="\t")
        x = x+1
    print()
    y = y+1

31. Szorzótábla

y = 1
while y <= 10:
    x = 1
    while x <= 5:
        print(x * y, end="\t")
        x = x+1
    print()     # új sor
    y = y+1
1       2       3       4       5   
2       4       6       8       10  
3       6       9       12      15  
4       8       12      16      20  
5       10      15      20      25  
...

Példa: a szorzótábla kirajzolása két ciklussal. Kívül a sorok ciklusa (y, tíz iteráció), és azon belül soronként öt szám (x, öt iteráció soronként) és egy új sor kezdése. Az x változó csak a belső ciklushoz van, így azt érdemes ott létrehozni, mert csak ott használjuk.

Figyeljük meg:

  1. A kód tördelése. Az egyes vezérlési szerkezetek belsejében lévő utasítások beljebb kezdődnek. Ez nemcsak hogy kötelező a Pythonban, de a megértést is segíti: látjuk a szorzáson egyből, hogy az cikluson belüli ciklusban van.
  2. A változódefiníciók helye. A Python megengedi azt, hogy bárhol változót hozzunk létre. Jelen esetben az x nevű változót az x-es ciklus előtt hozzuk létre, közvetlenül annak while kulcsszava fölött. Nem máshol! Ahhoz a ciklushoz tartozik, ahhoz legyen közel. Ez is a program érthetőségét növeli.
  3. A tabulátor karakter. Az egyes kiírt számok közé "\t"-t, tabulátor karaktert teszünk. Ez mindig ugrik az ablakban a következő 8-cal osztható sorszámú oszlopra, így a számok egymás alá tudnak kerülni. Így persze sajnos a számok nem helyiérték szerint szerepelnek egymás alatt, de később lesz szó róla, hogyan lehet ezt szebben megoldani.
\
visszaper
(backslash)

A \ visszaper (backslash) karakter a sztringekben speciális karaktereket jelöl meg. A fenti kódban is a \t jelentése nem az, hogy ki kell írni egy visszapert, utána pedig egy t betűt; hanem a két karakter együtt egyetlen egy tabulátort jelképez. Léteznek más vezérlőkódok is. Például a \n, amellyel egy sztring közepére is írhatunk sortörést:

print("Hello,\nvilág!")
Helló,
világ!

Arra is jó a \, hogy idézőjelet tegyünk egy sztringbe. Innen tudja majd a gép, hogy a következő idézőjel nem a sztring befejezése, hanem csak egy olyan idézőjel, ami része a szövegnek:

print("London Anglia fővárosa.")
print("\"London\" egy hat betűs szó.")
London Anglia fővárosa.
"London" egy hat betűs szó.

Persze ezt úgy is megoldhattuk volna, hogy magát a sztringet aposztrófok közé tesszük: a Python azt is elfogadja. Az aposztrófok közé tett sztringben az idézőjelnek semmilyen különleges szerepe nincs:

print('London Anglia fővárosa.')
print('"London" egy hat betűs szó.')
London Anglia fővárosa.
"London" egy hat betűs szó.

Az aposztróf és az idézőjel karaktereket angolul gyakran single quote-nak és double quote-nak is nevezik.

32. Vezérlési szerkezetek: összefoglalás

Strukturált programok (structured programs)

  • Amelyek szekvenciából, elágazásból és ciklusból épülnek fel
  • Matematikailag bizonyított: minden számítógéppel megoldható feladat megoldható így!

szerkezethasználatPython
szekvenciaEgymás utáni utasítások.utasítás1
utasítás2
utasítás3
elágazásFeltételhez között végrehajtás.
0-szor vagy 1-szer.
if feltétel:
   utasítás
ciklusIsmétlés.
0-tól ∞-ig akárhányszor.
while feltétel:
   utasítás

Programvezérlés (control flow)

Az utasítások végrehajtásának sorrendje.

  • Alapvetően egymás után, de ez megváltoztatható vezérlési szerkezetekkel (control structure).
  • Speciális programbeli utasítások tartoznak hozzájuk: ezek a vezérlésátadó utasítások (control flow statement).
Spagetti kód

A vezérlési szerkezetek lényege az, hogy valamilyen döntés (egy feltétel teljesülése) alapján máshol folyatódik általuk a program végrehajtása – nem a sorban következő utasításnál. A Python egyébként nem is enged mást, csak ezeket a vezérlési szerkezeteket. Nem ugrálhatunk ide-oda a programunkban, nem írhatunk ún. spagetti kódot.

A spagetti kóddal az a baj, hogy az ugrásoknál sose tudni, mire valók, mi a céljuk. Elágazást szeretnénk, elvégezni egy műveletet vagy átugrani, kihagyni? Vagy azért ugrunk valahova, mert meg szeretnénk ismételni valamit? Folyton keresgélni kell a kódban, hogy előre vagy hátrafelé ugrunk, beleugrunk egy műveletsor belsejébe, kiugrunk belőle, megszakítva azt.

A vezérlési szerkezeteknek az is az értelme, hogy jelezni tudjuk, miért ugrunk, mire használjuk az ugrást. Amikor visszaugrunk egy pontra a programban, általában azért tesszük, hogy megismételjünk egy műveletet, műveletsort. Ha előrefelé, azt pedig azért, hogy kihagyjunk egy műveletet, hogy feltételhez kössük annak végrehajtását. Különböztessük meg ezeket, rendeljünk ezekhez különálló vezérlésátadó utasításokat! Ha így teszünk, sokkal érthetőbb lesz a programunk.

33. A Python nyelv elemei

NévPéldaHasználat
kulcsszó (keyword)while, ifa nyelv része, valamilyen speciális jelentése van
azonosító (identifier)x, teruletvalami neve, pl. változóé
operátor (operator)* + / **számítási művelet
megjegyzés (comment)# magyarázatprogramozóknak szóló, megértést könnyítő szöveg
szám (numeric)12, 6.0e23egész és valós számok
sztring (string)"helló, világ"szöveg

Érdemes ezen nyelvi elemek neveit magyarul és angolul is ismerni; a szakirodalomban és a gép hibaüzeneteiben rengeteget találkozunk velük.

A számokat és a sztringeket összefoglaló néven literálisoknak nevezzük (literal). Ezek azok a részek a forráskódban, amiket szó szerint kell érteni. Egy változónál ez nem igaz, mert a változóval igazából a benne tárolt értéket hivatkozzuk meg valójában.

A nyelvtan leírása

Érdemes tudni róla, hogy a programozási nyelvek nyelvtani szabályait formálisan is rögzíteni szokták. Egyik nyelv, amivel nyelvtani szabályok leírhatók, az ún. EBNF, Extended Backus-Naur Form. Ennek jelölései a következők:

JelölésJelentésPélda
::=definíciónévelő ::= "egy"
" "szöveg
|„vagy”számjegy ::= "0" | "1" | …
összefűzés (nincs jelölve külön)negatív ::= "-" szám
[ ]elhagyhatópozitív ::= ['+'] szám
*ismétlés (akár 0)sztring ::= ' " ' karakter* ' " '
+ismétlés (1 vagy több)szó ::= betű+

Példaként a pozitív egész szám nyelvtani szabályainak leírása EBNF-ben:

szám ::= nemnulla számjegy*
számjegy ::= "0" | nemnulla
nemnulla ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
  • Akárhány számjegyből állhat, nem kezdődhet nullával; mert a legelső számjegyet a nemnulla szabály definiálja, a többit a számjegy.
  • Helyes: 98, 54079, 43, 1, 112.
  • Helytelen: 1ax, abcd, s98, 012.

A Python nyelv dokumentációja is tartalmaz EBNF szabályokat. De ebből dolgoznak azok is, akik a fordítóprogramot írják: ha matematikai precizitással adottak a nyelvtani szabályok, akkor a nyelv minden mondatát könnyű értelmezni.