Még mielőtt akárminek is nekikezdenék, szeretném jelezni, hogy igazodva a kor igényeihez, ez a bejegyzés 2016. február 26-án újraírásra került. Az eredeti bejegyzés még a Python 2.7.3 használatával készült. Azóta gyakorlatilag az összes jelentős csomag Python 3 kompatibilis verziója elkészült, és magam is napi rendszerességgel Python 3 nyelvű fejlesztéssel foglalkozok.
Ideje folytatni az előző bejegyzésben elkezdett témát. Hogy kerek legyen a történet, foglalkozzunk kicsit az operátorokkal.
Mik azok az operátorok?
Az operátorok olyan elemi műveletek amikre a programozási nyelv képes. Amikor programot írunk, akkor ezeknek az egyszerű műveleteknek a véges sorozatát írjuk le. Ahhoz pedig hogy abból egy jól működő program legyen csupán a logikánkat kell majd használni.
Már az előző bejegyzésben is találkoztunk pár operátorral, ilyen volt a =
, vagy a +
. Ezek ismerősek lehetnek a matek órákról, nem véletlenül: a legtöbb matematikai művelethez létezik operátor a Pythonban. Az operátoroknak általában két kifejezéssel dolgoznak: az egyik az operátor bal, a másik a jobb odalára kerül. Ezeket a kifejezéseket operandusoknak hívják.
Nem kell a matek szótól hirtelen pánikot kapni, a programozás Pythonban nem egyenletmegoldásokról szól. Részemről, amikor programozok, vannak olyan napjaim, amikor a legbonyolultabb matematikai kifejezés amit írnom kell az egy egyszerű összeadás. A többi napon még annyi sincs.
Aritmetikai operátorok
Aritmetikai műveletek általában azok amiket számokon értelmezünk. Pythonban ez a fogalom jócskán ki van bővítve, mert objektumokon is értelmezhetőek egyes operátorok. Erről majd később beszélünk egyszer.
Lássuk a leggyakoribb operátorokat:
=
Értékadás (assignment). Vele már találkoztunk az előző részben, most akkor beszéljünk kicsit a működéséről is. Az értékadás mindig jobbról-balra történik, azaz a jel jobb oldalán álló kifejezés eredménye bekerül a bal oldalon álló változóba.+
Összeadás (add). Konstansok, változók értékeit adatjuk össze vele, de összefűzést is jelent (ahogy az előző részben azt be is mutattam).-
Kivonás (substract). Erről nem is érdemes többet beszélni.*
Szorzás (multiply)./
Osztás (divide). Kétint
osztása egyfloat
-ot eredményez, még akkor is, ha az eredmény amúgy kerek, nem tört (így tehát ez a való osztás, és mellékesen itt implicit típuskonverzió történt). Bár mára ez már történelem, de anno a Python 2-ben ez az operátor mindigint
-et eredményezett, tehát szépen lehagyta a törtet az eredményről.//
Egész osztás (integer division). Ha ennek az operátornak mindkét oldalánint
szerepel, akkor az eredménye isint
típusú lesz, még akkor is, ha az eredménye amúgy nem egész. Ilyenkor a törtrész elhagyásra kerül. Tehát a11 // 2
értéke 5. Negatív számoknál kicsit trükkösebb, mert a-11 // 2
eredménye -6. Tehát valójából az érték lefelé, a kisebb érték felé kerekítődik.%
Maradék képzés (modulo vagy remainder). Ez az operátor azt mondja meg, hogy két tört osztásának mennyi a maradéka. Aki régen osztott papíron az lehet már elfelejtette hogy mi is az pontosan, úgyhogy itt egy példa:7'1'3 : 2 = 356 1 1 1 3 1 <- Ezt a számot kapjuk eredményül
A színezésre ne figyeljetek
Mire jó ez az operátor? Például arra, hogy eldöntsük jól egy számról, hogy páros-e vagy páratlan (ha a maradék 1 akkor páratlan, amúgy páros).**
Hatványozás (power). Az operátor bal oldalán a hatványalap, jobb oldalán a hatványkitevő áll.
A fenti operátorokkal egy csinos kis számológéppé léptettük elé a Pythont.
Logikai operátorok
Mint ismeretes, a számítógépek a bűvös kettes számrendszert használják. Egyesek és nullák, régi történet. A logikai műveletekkel gyakorlatilag egyértelműen eldönthető kérdéseket teszünk fel a számítógépre, amire ő igennel vagy nemmel tud felelni, vagy inkább igazzal vagy hamissal, ami angolul True
vagy False
, számítosítva meg 1 és 0. Meg is érkeztünk a kettes számrendszerhez.
Az ilyen kérdésekre (hívjuk feltételeknek) kapott válaszokkal tudunk dolgozni. Nézzük milyen operátorok tudnak segíteni ebben:
==
Egyenlőség (equal). Logikai értékeTrue
ha a két kifejezés egyenlő. Így vizsgálhatjuk hogy egy változó érték egyelnlő-e egy értékkel, és hasonlók.!=
“Nem egyenlőség” (not equal). Tehát ez az operátor arra ad választ, hogy a bal- és jobb oldala különböző-e.>
Nagyobb (greater). Avagy a jó öreg kacsacsőr. Akkor eredményezTrue
-t, ha a bal kifejezés nagyobb mint a jobb.<
Kisebb (less). Akkor eredményezTrue
-t, ha a bal kifejezés kisebb mint a jobb.>=
Nagyobb egyenlő. Akkor eredményezTrue
-t, a a bal kifejezés nagyobb vagy egyenlő a jobb oldalival. A félreértések elkerülése végett, bár ez két karakter, egyetlen operátort jelöl, tehát nem lehet helyette olyat írni hogy=>
, mert az nem létezik.<=
Kisebb egyenlő. Akkor eredményezTrue
-t, ha a bal oldali kifejezés kisebb vagy egyenlő a jobb oldalival. Ugyan az igaz az írására, mint a>=
esetén.or
“Vagy”. Bizony, ezt normális latin betűkkel, és nem hieroglifákkal kell írni. Akkor eredményezTrue
-t, ha a két oldalán álló kifejezések közül bármelyikTrue
. Ez akkor jön majd jól, ha olyan algoritmust írunk aminek a futása több dologtól is függ, de elég, ha azok közül legalább egy logikailag igaz.and
“És”. Akkor eredményezTrue
-t, ha mindkét kifejezés az oldalánTrue
. Ez meg majd akkor jön jól, ha olyan algoritmust írunk, aminek a futásához egyszerre mindennek klappolnia kell, tehát mindenkinek logikailag igaz értékkel kell rendelkeznie.not
“Nem”. A logikai kifejezés tagadása, negációja. A többiekkel ellentétben ez egy egy operandusú művelet, tehát ennek csak a jobb oldalára kell írni kifejezést.True
-raFalse
-t,False
-raTrue
-t eredményez.
Ezzel véget ért egyelőre a felsorolás, de még akadnak más operátorok is a Python nyelvben. Elég csak az előző részben említett index operátorra gondolni. Ezeket az operátorokat a rájuk jellemző adatstruktúrákkal együtt ismertetem, így lehet majd mihez kötni őket.
Ezeket az operátorokat ugyan úgy írhatjuk kifejezések közé, mint az aritmetikaiakat, de ne felejtsük el, hogy ezek mindig valamilyen bool
típusú értéket eredményeznek. Lássunk egy rövid példát:
print(1 == 2)
print(1 > 0 and 1 > -1)
Ha ezt lefuttatjuk, akkor először a False majd a True üzenet jelenik meg a konzolban. Ez teljesen logikus, hisz nem igaz hogy az 1 egyenlő lenne a 2-vel, viszont az igaz, hogy az 1 nagyobb mint a 0 és az 1 nagyobb mint a -1.
Igazságtáblák
A logikai operátoroknak elég jól behatárolt, és nagyon kevés bemenete és kimenete létezik, ezért ezekett táblázatokba szokták gyűjteni, ez az igazságtábla. A fenti utolsó 3 operátor igazságtáblái ezek:
or
A | B | A or B |
---|---|---|
False | False | False |
False | True | True |
True | False | True |
True | True | True |
and
A | B | A and B |
---|---|---|
False | False | False |
False | True | False |
True | False | False |
True | True | True |
not
A | not A |
---|---|
False | True |
True | False |
Rövidzár
Az and
és az or
operátorok képesek a rövidzárásra (short circuit). Ez azt jelenti, hogy ha az első operandus alapján biztos a művelet eredménye, akkor a második operandus nem kerül kiértékelésre. Nézzünk néhány példát:
True or print('Második operandus')
False and print('Második operandus')
Ha ezt a programot lefuttatjuk, akkor a konzolban semmi se jelenik meg. A szerint amit feljebb írtam, az első sorban az or
első paramétere alapján már biztos hogy True
lesz az eredmény, így a futás rá se ugrik a print()
-re.
A második sorban, ha az and
első operandusa False
akkor biztos hogy False
lesz az eredmény, és nem is kerül futtatásra a print()
.
Ez egy fontos tulajdonság, és nagyon hasznos tud lenni olyan szituációkban, amikor olyan kifejezést írunk, amikor tilos a második operandus kiértékelése akkor, ha az első nem teljesült.
Kifejezések
Az előző jó néhány bekezdésben gyakran jelent meg a kifejezés fogalma. Ennyi szöveg után ideje ezt is elamgyarázni.
A kifejezések a forráskód elemi részei. Egyesek egymásba is ágyazhatóak, tehát léteznek összetett kifejezések.
Ahogy leírjuk egy Python fájlban azt hogy:
number = 1 + 2
Úgy valójában 4 kifejezést hoztunk létre:
- Vettük az
1
mint konstans kifejezést - Vettük a
2
mint konstans kifejezést - Előállítottunk egy újabb kifejezést úgy, hogy alkalmaztuk az összeadás műveletét a két konstansra.
- Az előbb létrejövő kifejezés eredményét (ami az összeadás eredménye) az értékadó operatár eltárolta a
number
nevű változóban.
Ha ezt realizáltuk, akkor látható, hogy szinte végtelen mélységig pakolgathatóak egymásba a kifejezések, egyáltalán nem kötelező változókba pakolászni részeredményeket. Egy kérdés maradt már csak: ha egy sornyi kifejezést írok le, milyen sorrendben kerülnek kiértékelésre?
Kiértékelési sorrend
A kiértékelési sorrend (order of operations), avagy erősebb kutya baszik, olyan dolog, amivel soha többé nem találkozik az ember az általános iskola után, egész addig, amíg a Facebookon már megint fel nem bukkan egy olyan furmányos talány hogy:
7 - 1 * 0 + 3 / 3 = ?
Az emberek 74%-a hibás eredményt az erre az egyszerű kérdésre.
Akkor most tápoljuk be egy programba:
print(7 - 1 * 0 + 3 / 3)
Az eredmény természetesen 8. Hogy miért? Mert a számítógép soha nem bassza el.
A programozási nyelvekben, így a Pythonban is, a kifejezések kiértékelési sorrendje balról jobbra történik, és bentről kifelé, pont úgy, ahogy a matematikában. Egyes operátorok előnyt élveznek a többiekkel szemben. A sorrend (először a legerősebb, végül a leggyengébb):
**
*
,/
,//
,%
+
,-
<
,<=
,>
,>=
,!=
,==
not
and
or
Így már teljesen világos hogy miért is 8 az eredmény.
A zárójel
Ahogy a matematikában, úgy a programozásban is előfordul, hogy ki akarjuk kényszeríteni a kifejezések kirétékelési sorrendjét. Ez megszűnteti az olyan problémákat is, mint hogy ki a faszom emlékezett arra, hogy a szorzás előbb következik mint az összeadás.
Zárójelet bárhol alkalmazhatunk a kifejezésben. Írjuk át a fentit hogy egyértelmű legyen:
print(7 - (1 * 0) + (3 / 3))
Ó, hát persze, 1 * 0
az 0, ezt minden hülye tudja!, 3/3
az 1. És akkor 7 - 0 + 1
az 8.
Zárójelet használni semmibe se kerül, cserébe megelőz minden félreértésből adódó problémát. Nem kell spórolni vele.
Önmarágra hivatkozó változó
Kiemelném azt az esetet, amikor az értékadás mindkét odalán ugyan az a változó szerepel.
Mi történik akkor ha leírjuk hogy:
number = 1
number = number + 1
Az 1. sorban csak deklaráltuk a változót. A második sorban viszont a változónak értékül adtuk saját magát úgy, hogy még 1-et hozzá is adtunk. Ez teljesen normális, hisz a jobb oldallal kezdődik a kiértékelés. Ekkor a number
egy létező változó, az összeadás értelmezhető rá. A kifejezés értékét (ami 2 lesz) ez után felveszi a number
.
Utasítások
Végére maradtak az utasítások. Ezek olyan kifejezések, amikből a forráskód egy sorában egy, és csak az az egy állhat, így tehát nem ágyazhatóak egymásban. Kiértékelésüket tekintve először mindig az utasítás jobb oldala kerül kiértékelésre, és csak legvégül az utasítás maga. Mindig egy operandusúak… már ha beszélhetünk operandusról, a szó szoros értelmében.
Elsőre ez eléggé szigorú megszorításnak tűnik, de ide tartozik az értékadás is. Az értékadás ugyanis nem ágyazható bele semmibe, és egy sorban nem lehet több értékadást egyszerre csinálni még ha úgy is tűnik mintha azt tettük volna.
Egyelőre tehát csak az értékadást, mint utasítást ismerjük, de rövidesen jönnek olyan finomságok, mint az elágazások, ciklusok utasításai, és akkor aztán végre elkezd úgy dolgozni a CPU ahogy kell.
Zárás
Most hogy ennyi mindent megtudtuk arról hogy mennyire jó a Python a matekból a következő részben végre bevonjuk a felhasználót is a játékba!
Ez a bejegyzés a Python tutorialom egyik része. Az összes rész listája itt fellelhető.
-slp