Változótípusok és számolás pythonban

**Ha valaki az igazságot és a törvényszerűséget keresi, nem tehet különbséget kicsiny és nagy problémák között.
Aki a kicsiny dolgokban nem veszi komolyan az igazságot, abban az emberben nagy dolgokkal kapcsolatban sem bízhatunk meg.**
*Albert Einstein*

Ebben a Notebookban bemutatjuk a python nyelv szintaxisát és néhány alapvető adat típust és adatstruktúrát. Illetőleg megnézzük hogyan lehet a pythonban egyszerű matematikai műveleteket elvégezni.

Adattípusok

Komment (megjegyzés)

A Pythonban a megjegyzések kettős-kereszttel ('#') kezdődnek és a sor végéig tartanak. Egy megjegyzés lehet sor elején, vagy követhet szóközt, tabulátor-karaktert, de ha egy karakterlánc (string) belsejébe teszed, az nem lesz megjegyzés (lásd a példában!). A kettős-kereszt karakter egy karakterláncon belül csak egy kettős-keresztet jelent.

In [ ]:
# ez az első megjegyzés
SPAM = 1                 # ez a második megjegyzés
                         # ... és ez a harmadik.
STRING = "# Ez nem megjegyzés, mert idézőjelekben van."

A comment csak a programozónak szól emlékeztetőül, vagy más programozók megértését segíti. Noha gyakran elmarad, a kódok rendszeres dokumentálása megjegyzésekkel, később (amikor már a kód részleteit a feledés homály borítja) nagyon kifizetődő lehet.

Számok

A Pythonban, mint a programozási nyelvekben többféle számtípust tudunk megkülönböztetni. A különbségtétel oka, hogy miként tudja a program a memóriában tárolni a számokat illetve a CPU (a számítógép számolási feladatait ellátó részegység) miként képes kezelni őket.

A Pythonban megkülönböztetjük többek között az egész (integer) számokat:

In [ ]:
A=2
print(type(A))
print(A)

Vannak lebegőpontos számok (tizedes ponttal ellátott véges hosszú számok):

In [ ]:
B=3.25
print(type(B))
print(B)

Karakterláncok (Stringek)

A számok mellett a Python karakterláncokkal is tud műveleteket végezni. A karakterláncokat egyszeres ('...') vagy dupla idézőjelek ("...") közé lehet zárni. A két jelölés között nincs jelentős különbség. A \ használható arra, hogy a karakterláncbeli idézőjeleket levédjük:

In [ ]:
'spam eggs'
In [ ]:
'doesn\'t'
In [ ]:
"doesn't"
In [ ]:
"\"Yes,\" he said."

A kimeneti karakterlánc idézőjelekben jelenik meg, és a speciális karakterek vissza-perrel () levédve. Bár ez néha különbözőnek látszik a bemenettől (az idézőjel fajtája megváltozhat), a két karakterlánc egyenértékű. A print() függvény egy sokkal olvashatóbb kimenetet eredményez, elhagyva az idézőjeleket és kiírva a levédett és speciális karaktereket:

In [ ]:
'"Isn\'t," she said.'
print('"Isn\'t," she said.')
In [ ]:
s = 'First line.\nSecond line.'  # \n újsort jelent
s  # print() nélkül a \n benne van a kimenetben
print(s)  # print()-tel az \n újsort hoz létre

print('C:\some\name')  # \n újsort jelent
print(r'C:\some\name')  # r van az idézőjel előtt --> Meggátolja a \. értelmezését

Karakterláncokat a + művelettel ragaszthatunk össze és *-gal ismételhetünk.

In [ ]:
3 * 'un' + 'ium'

Két egymást követő literális karakterláncot (azokat, amik idézőjelben vannak, és nem egy változóban, vagy nem egy függvény hoz létre) az értelmező magától összefűz:

In [ ]:
'Py' 'thon'
In [ ]:
prefix = 'Py'
prefix + 'thon'  # csak így tud változót és literális karakterláncot összefűzni

A karakterláncokat indexelhetjük, az első karakterhez tartozik a 0 index, a következőhöz az 1-es index és így tovább. Nincs külön karakter típus; egy karakter egyszerűen egy egy hosszúságú karakterlánc:

In [ ]:
szo = 'Python'
szo[0]  # karakter a 0 pozícióban

Az indexek negatívak is lehetnek, ilyenkor jobbról kezdünk el számolni:

In [ ]:
szo[-2]  # utolsó előtti karakter

Az indexelésen felül a szeletelés is támogatott. Míg az indexelés egyetlen karaktert jelöl ki, a szeletelés egy rész-karakterláncot:

In [ ]:
szo[2:5]  # karakterek a 2 pozíciótól (benne van) a 5-esig (az már nem)
In [ ]:
szo[:2]  # karakterek az elejétől a 2-esig (már nincs benne)
In [ ]:
szo[42]  # a szo csak 6 karakteres

A beépített len() függvény a karakterlánc hosszával tér vissza:

In [ ]:
s = 'legeslegelkáposztásíthatatlanságoskodásaitokért'
len(s)

Listák (List)

A Python többfajta összetett adattípust ismer, amellyel több különböző értéket csoportosíthatunk. A legsokoldalúbb a lista, amelyet vesszőkkel elválasztott értékekként írhatunk be szögletes zárójelbe zárva. A lista elemeinek nem kell azonos típusúaknak lenniük, bár gyakran minden elem azonos típusú.

In [ ]:
a = ['spam', 'tojások', 100, 1234]
a
['spam', 'tojások', 100, 1234]
In [ ]:
a[3]
In [ ]:
a[2] = a[2] + 23
a

A listák egymásba ágyazhatóak, azaz listába elhelyezhetünk listát elemként:

In [ ]:
a = ['a', 'b', 'c']
nn = [1, 2, 3]
x = [a, nn]
x

Logikai Bool-változók és feltételes végrehajtás

Ahhoz hogy a program reagálni tudjon bemenetekre, vagy egy már kiszámolt részeredménytől függhessen további működése, szükség van feltételek vizsgálatára. Gondoljunk például a másodfokú egyenlet megoldóképletére! Attól függően, hogy a diszkrimináns pozitív vagy negatív léteznek ill. nem léteznek valós gyökök, így értelemszerűen egy ilyen programnak "döntenie" kell. A döntés, egy feltétel vizsgálatán alapul (pl. poz. vagy neg. diszkrimináns), ami lehet igaz, vagy hamis, angolul True ill. False. Az igaz és hamis értéket tárolni képes változó típusa: boolean (Bool-változó). (Emlékezzünk vissza az int ill. float típusokra).

Két objektum azonosságáról dupla egyenlőségjellel, azaz a == operátor segítségével tájékozódhatunk.

In [ ]:
1 == 1  # 1 megeggyezik 1-el ?
In [ ]:
1 == 2 # 1 megeggyezik 2-vel ?
In [ ]:
1 == '1'

Ha arról akarunk meggyőződni hogy két objektum nem ugyan az akkor ezt a != operátor segítségével tehetjük meg:

In [ ]:
1!=2 #1 nem 2 ?
In [ ]:
1 != 1

Természetszerűen számok esetén a <,> operátorok segítségével dönthetjük el hogy melyik szám a nagyobb:

In [ ]:
1>2
In [ ]:
1<2
In [ ]:
1 < '1'

Egy igaz/hamis értéket változóban is tárolhatunk:

Bool változók és más változók kapcsolata

Ahogy fenntebb láttuk egy objektumot egész számmá (int() függvény) vagy lebegőpontos számmá tudunk konvertálni ( float() függvény). Objektumokat Bool-változóvá is tudunk konvertálni. Erre szolgál a bool() függvény. Alább néhány példát nézzünk meg hogy bizonyos dolgok hogy konvertálódnak a bool() függvénnyel.

egy szám vagy egy karakterlánc True értéket ad:

In [ ]:
print(bool(1.0))
print(bool('szoveg'))

Egy látszólag rosszul működő példa:

In [ ]:
'b' == ('a' or 'b') 
In [ ]:
'a' == ('a' and 'b') 
In [ ]:
'b' == ('a' and 'b') 
In [ ]:
'a' and 'b'

A második példa vajon miért False ha az első True ? A harmadik miért False ha a látszólag hasonló negyedik True? Ezen a ponton úgy tűnhet hogy az and és or utasítások nem működnek megfelelően! Ha részletesen kiböngésszük hogy mit is csinál a python értelmező akkor kiderül hogy pontosan azt teszi amire megkértük.. DE ez nem pontosan az amire elsőnek gondolnánk! Az első két példa tehát nem azt ellenőrzi hogy a == előtt álló karakter az szerepel-e a zárójelben! Mi is történik pontosan? Amikor a python egy or kifejezéssel találkozik (a zárójeleken belül) sorba megy az or kifejezés által kapcsolatba hozott elemeken és az első True - ként kiértékelhető objektum értékét adja vissza, tehát nem True vagy False-t hanem a változó értékét. Ez azért van így mert ha egy or kifejezés egyik tagja igaz akkor az egész kifejezés igaz. Az and ezzel szemben addig lépdel végig az alkotó kifejezéseken amíg meggyőződött róla hogy mindegyik kifejezés igaznak számít és a legutolsó értéket adja vissza. A bool operációk ezen viselkedését rövid zár-nak hívják és sok programozási nyelvben hasonlóan működik. Tehát ha arról akarunk meggyőződni hogy egy kifejezés valamely kifejezés csoport egyikével megegyezik akkor az alábbiak szerint szükséges eljárni:

In [ ]:
print((('a' == 'a') or ('a' == 'b')))
print((('b' == 'a') or ('b' == 'b')))

Előfordul azonban sokszor hogy az a csoport amihez egy lehetséges elemet össze kell hasonlítani igen népes. Például hogy mondjuk meg hogy egy karakterlánc szerepel egy adott hosszú listában? Erre alkalmazható az in kulcsszó:

In [ ]:
Tage_der_Woche=['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag']
print('hetfo' in Tage_der_Woche)
print('Montag' in Tage_der_Woche)

Python mint számológép

A notebookot lehet úgy használni akárcsak egy sima számológép: be lehet írni egy kifejezést, és az kiszámolja az értékét. A kifejezések nyelvtana a szokásos: a +, -, * és / műveletek ugyanúgy működnek, mint a legtöbb nyelvben (például Pascal vagy C); zárójeleket (()) használhatunk a csoportosításra. Például:

In [ ]:
2 + 2
In [ ]:
50 - 5*6

Az egész számok (pl. 2, 4, 20) alkotják az int típust, azok, a valós számok (pl 5.0, 1.6) pedig a float típust. A python 3-ban az osztás (/) mindig lebegőpontos értékeket ad vissza. Lefelé kerekítő egész osztás elvégzéséhez, amellyel egész értéket kapunk a // operátor használható; az osztás maradékához a %:

In [ ]:
(50 - 5*6) / 4
In [ ]:
8 / 5  # az osztás egész számok esetén is lebegőpontos eredményt ad. 
In [ ]:
17 / 3  # hagyományos osztás lebegőpontos eredménnyel
In [ ]:
17 // 3  # az egész osztással megszabadulunk a törtrésztől
In [ ]:
17 % 3  # a % operátor az osztás maradékával tér vissza
In [ ]:
5 * 3 + 2  # eredmény * osztó + maradék
In [ ]:
5 ** 2  # 5 négyzete
In [ ]:
2 ** 7  # 2 7-dik hatványa
Biztos jól számolunk? A lebegőpontos számok véges hosszúak, és a számítógép csak adott hosszú részt vesz figyelembe!
In [ ]:
C=0.1 - 0.1000000000000000055511151231257827021181583404541015625   #  Biztos jól számolunk?
print(C)
In [ ]:
D=(1/29999999999999999)*30000000000000000
print(D-1)

Az itt látható hiba nagyon gyakori hiba a numerikus programokban. Nagyon figyeljünk a számábrázolási hibára, hiszen ez az apró eltérés, hibás működéshez vezethet (amit nem mindig jelez a rendszer hibaüzenettel!):

In [ ]:
10/(D-1.0)

A C-hez hasonlóan az egyenlőségjellel (=) lehet értéket adni egy változónak. Az értékadás után az értelmező újabb utasításra vár, látszólag nem történik semmi:

In [ ]:
szelesseg = 20
magassag = 5*9
In [ ]:
szelesseg * magassag

Ha egy változó nincs definiálva (nincs érték rendelve hozzá), és használni próbáljuk, akkor hibaüzenetet kapunk:

In [ ]:
nnn  # Az n válltozót még nem definiáltuk

A programnyelv teljes körűen támogatja a lebegőpontos számokat; azok a műveletek amelyeknél keverednek a típusok, az egészeket lebegőpontossá alakítják:

In [ ]:
3 * 3.75 / 1.5

Előfordul néha hogy egyes függvények int típusú változót várnak és ezt egy float típusúból kell előállítanunk. A típusok közti konverziót az int() és float() függvények segítségével tehetjük meg.

In [ ]:
int(3.1415)
In [ ]:
float(42)

A Python komplex számokat is tud kezelni – a képzetes részt a j vagy J jellel képezhetjük. A komplex számot (valós+képzetes "j") formában írhatjuk:

In [ ]:
1j * 1J
In [ ]:
(1+2j)/(1+1j)

A komplex számokat gyakran két lebegőpontos számmal ábrázolják: a képzetes és a valós résszel. A z komplex számnak ezeket a részeit a z.real és z.imag utasításokkal olvashatjuk vissza.

In [ ]:
a=1.5+0.5j
In [ ]:
a.real
In [ ]:
a.imag

Az utoljára kiírt kifejezés értéke a _ (alsó-vonás) változóban van. Így, ha a Pythont asztali számológépként használod, akkor egyszerűbb folytatni a számolásokat, például:

In [ ]:
ado = 12.5 / 100
ar = 100.50
ar * ado
In [ ]:
ar + _
In [ ]:
int(round(ar, 0)) #kerekítés 2 tizedes jegyre