Bevezetés a Python nyelvbe

Az előadás nagyvonalakban a hivatalos Python tutorial-t követi.

A Python egy olyan általános körben használható magas szintű programozási nyelv, aminek az egyik alapelve az olvasható kód írása egy nagyon tiszta szintaxis használatával. 1991-ben alkotta meg Guido Van Rossum.

Nevét a Monthy Python ihlette, nem az állat.

Miért Python?

Népszerűsége

Előnyei

  • Könnyen tanulható, interaktív, kezdőknek ideális (ld. Raspberry Pi)
  • A kód könnyen olvasható, bonyolult feladatokra egyszerű parancsok
  • Több rendszeren, platformon fut
  • Objektumorientált
  • Web-programozásra alkalmas (Google, Yahoo, IBM, NASA, Disney, Dropbox,...)
  • Gyors fejlesztés, rövid kód, nagy feladatokra is alkalmas
  • Források nagy száma
  • Az adattudományban (data science) erős
  • Nyílt forráskódú, szabadon hozzáférhető, használható, üzleti célra is

Hátrányai

  • Lassú
  • Mobil-programozásra nem a legjobb
  • Nagy grafikai igényű (3D) programozásra nem alkalmas

Futtatás

  • a python ú.n. interpretált nyelv
  • egy általunk írt kód lefuttatásához egy másik programra van szükségünk: ú.n. interpreter
  • a futtató program bináris kódban van (azt sem abban írták, de arra fordították)
  • az általunk írt kód gép és operációs rendszer független (többnyire), a futtató program gép illetve oprendszer függő.

Több módon is futtathatunk python kódot.

Parancssorból

Parancssorból futtatható, pl interaktívan: $ python Ekkor interaktív pythont kapunk amibe közvetlen írhatunk parancsokat.

De lefuttathatunk parancssorból egy létező python file-t is (.py kiterjesztésű file): $ python hello.py Ekkor lefut a program és ha van szöveges kimenete a programnak az látható lesz a parancssorban.

Itt az interpreter a python(.exe)

Jupyter (IPython) notebook

A Jupyter egy böngészőn keresztül használható fejlesztői környezet pythonhoz, mely a tavalyi Sage notebookhoz hasonlít. Ez az amit az előadás írásához használunk és gyakorlaton is fogjuk használni.

Indítani egy IPython szervert a következő paranccsal tudunk a leibniz-en: $ ipython notebook --port=##### --no-browser --ip=127.0.0.1 Ahol a ##### helyére egy 9000 és 20000 közti számot írjunk. Ekkor böngészőben a localhost:##### oldalon érhetjük el az IPython notebookunkat.

Itt a van egy program, ami a böngészőben látható felületet kezeli és az még több belső interpreter-t (kernel) is használhat. De az ipython maga is egy interpreter.

Az újabb verziókban az ipython notebook helyett a jupyter notebook parancs használatos (saját gépen könnyebb lesz). A Jupyter képes több kernelt is használni, pl a Python és a Sage is ilyenek, de más nyelvekhez is vannak kernel-ek.

Spyder

A Spyder egy grafikus fejlesztői környezet pythonhoz, a leibniz-en fent van de kényelmesen telepíti bárki bármilyen oprendszerre.

Ez nem interpreter, hanem egy program ami a kód írását és futtatását könnyíti meg, de muszáj használnia egy interpretert.

Otthonra

Az Anaconda disztribúciót javaslom. Van minden főbb asztali oprendszerre (Linux, Mac, Windows)

  • válasszuk ki a megfelelő oprendszert
  • válasszunk 2.7-es verziót (a leibniz-en ez van, ezért most ezt tanuljuk, de van újabb is)
  • figyeljünk, hogy 32 vagy 64 bites

Ez tartalmaz parancssori (python, ipython), notebook (jupyter) és grafikus (Spyder) környezetet is nem beszélve sok hasznos függvénykönytárról.

Objektumok

Az objektumok a nyelv alapelemei, ezekkel fogunk dolgozni. Minden objektumnak van típusa. A következő típusokkal kezdjük:

  • int (egész): 2354, -12
  • float (lebegőpontos szám): 1.0, -23.567, 2.3E4
  • bool (logikai): True, False
  • str (karakterlánc, sztring): "kiskutya", "Volt egyszer egy kiskutya"

Dolgok típusát lekérdezhetjük a type paranccsal.

In [1]:
type(5.0)
Out[1]:
float

Műveletek, kifejezések

Az objektumok műveletekkel összekapcsolva kifejezéseket adnak, melyek kiértékelve valamilyen típusú objektumot adnak. Az egész és a lebegőpontos műveletek:

  • a + b összeadás
  • a - b kivonás
  • a * b szorzás
  • a / b osztás (Python 2.7-ben int/int = int, Python 3-tól float)
  • a // b egész osztás
  • a % b maradékképzés
  • a ** b hatványozás (NEM a ^ b, mint a sage-ben!)
  • a == b, a < b, a > b, a <= b, a >= b, a != b, a <> b eredményük bool

Logikai műveletek bool-típusúak közt:

  • a and b, „és”
  • a or b, „megengedő vagy”
  • not a, „nem”

Stringeken alapvető műveletek:

  • a + b, konkatenálás
  • a in b, tartalmazás vizsgálat (eredménye bool)

Például

In [2]:
5 + 11
Out[2]:
16
In [3]:
2 ** 251
Out[3]:
3618502788666131106986593281521497120414687020801267626233049500247285301248L
In [4]:
a = 54
b = a - 50
a * b
Out[4]:
216
In [5]:
54 > 12
Out[5]:
True
In [6]:
b < 0
Out[6]:
False
In [7]:
54 > 12 or b < 0
Out[7]:
True
In [8]:
s = "macska"
"ma" in s
Out[8]:
True
In [9]:
s = "kis" + s
s
Out[9]:
'kismacska'

Változónevek

  • a név betűvel vagy aláhúzással kezdődhet: [_a-zA-Z]
  • a név további karakterei az előbbieken felül számok is lehetnek: [_a-zA-Z0-9]
  • elméletileg bármilyen hosszú lehet a név
  • név nem lehet foglalt szó
  • nagybetű-kisbetű érzékeny, tehát a val1 név nem azonos a Val1 névvel

Karakterláncok

Három módon adhatunk meg karakterláncokat:

In [10]:
s = "kiskutya"
type(s)
Out[10]:
str
In [11]:
s = 'kiskutya'
type(s)
Out[11]:
str
In [12]:
s = """Volt egyszer egy kiskutya.
Elment a vásárba."""
type(s)
Out[12]:
str
In [13]:
s
Out[13]:
'Volt egyszer egy kiskutya.\nElment a v\xc3\xa1s\xc3\xa1rba.'

Itt a vezérlő karaketerek (\n a sorvége jel) és az ékezetes karakterek UTF-8 kódja (á betű kódja c3a1, \x után a bájt hexa kódja) jelenik meg. A print utasítás olvashatóan írja ki:

In [14]:
print s
Volt egyszer egy kiskutya.
Elment a vásárba.

Az első kettőnek kényelmi szerepe van, mert amelyik idézőjelet nem használjuk a string jelzésére azt használhatjuk a stringben. Például:

In [15]:
print "Egy 'macskaköröm' " + 'ketto "macskaköröm"'
Egy 'macskaköröm' ketto "macskaköröm"
In [16]:
'Van ilyen: \' meg ilyen: "'
Out[16]:
'Van ilyen: \' meg ilyen: "'
In [17]:
print 'Van ilyen: \' meg ilyen: "'
Van ilyen: ' meg ilyen: "

A harmadikban használhatunk sortörést és ez a stringben is sortörésként fog megjelenni. Míg a többi jelöléssel sortörést a \n kifejezéssel tudunk tenni.

További speciális karakterek stringekben: \\\\ (\\), \' ('), \" ("), \n (új sor), \t (tab)

Kiírás

Itt a Jupyterben az egyes cellák eredménye az utolsó érték ami kiértékelődött, de például, ha parancssorban futtatunk egy korábban megírt python file-t, akkor még ez sem lesz kiírva. Ha valamit ki akarunk írni azt konkrétan meg kell tennünk:

In [18]:
5 + 8
5 + 7
Out[18]:
12
In [19]:
a = 5
print a
a = 15
print a * 2
a
5
30
Out[19]:
15
In [20]:
string = "kiskutya"
"Volt egyszer egy " + string
Out[20]:
'Volt egyszer egy kiskutya'
In [21]:
print "Volt egyszer egy %s, elment a vásárba." % string
Volt egyszer egy kiskutya, elment a vásárba.

Ha egy stringben %s szerepel akkor utána % jellel behelyettesíthetünk erre a pozícióra egy másik stringet. Több behelyettesítés esetén:

In [22]:
print "Volt %s egy %s, elment a %s." % ("egyszer", "kiskutya", "vásárba")
Volt egyszer egy kiskutya, elment a vásárba.

Nem csak stringeket lehet behelyettesíteni, egész vagy lebegőpontos számokat is lehet:

In [23]:
print """A %d egy decimális egész (integer), 
a %f pedig egy lebegőpontos (floating point) szám.""" % (23, 1.0/3)
A 23 egy decimális egész (integer), 
a 0.333333 pedig egy lebegőpontos (floating point) szám.
% típus példa eredmény
%s sztring "Volt egyszer egy %s" % "kiscica" "Volt egyszer egy kiscica"
%d egész "Volt egyszer %d kiscica" % 1 "Volt egyszer 1 kiscica"
%f lebegőpontos "Volt egyszer %f kiscica" % math.pi "Volt egyszer 3.141593 kiscica"
"Volt egyszer %d %s és osztozniuk kellett %fdkg sajton" % (3, 'kisegér', math.pi) "Volt egyszer 3 kisegegér és osztozniuk kellett 3.141593dkg sajton"

Egy sorba több dolgot is kiírhatunk, ha a print után vesszővel választjuk el. Ekkor szóközzel elválasztva lesznek kiírva.

Ha nem akarunk új sort kezdeni kiírás után, akkor a print-et fejezzük be egy vesszővel, jelezve hogy még folytatni akarjuk.

Üres print egyszerűen új sort kezd.

In [24]:
print 1, 3.14, "kutya"
print "macska",
print "teve",
print
print "vége"
1 3.14 kutya
macska teve
vége

Beolvasás

Ha már kiírni tudunk dolgokat, akkor tanuljunk meg beolvasni is:

In [25]:
raw_input()
macska
Out[25]:
'macska'
In [26]:
a = 5
nev = raw_input("Mi a neved? ")
print "Szia %s!" % nev
Mi a neved? Gábor
Szia Gábor!
In [27]:
input() > 10
5
Out[27]:
False
In [28]:
input() ** 10
5
Out[28]:
9765625

A különbség a raw_input és input között ez:

In [29]:
a = raw_input()
a + " macska"
5
Out[29]:
'5 macska'
In [30]:
b = input()
b + " macska"
5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-30-e6790e2fd4b0> in <module>()
      1 b = input()
----> 2 b + " macska"

TypeError: unsupported operand type(s) for +: 'int' and 'str'

Azaz a raw_input mindig stringként olvassa be bármit is adunk meg, míg az input megpróbálja értelmezni azt amit beírtunk:

In [31]:
type(input())
5.0
Out[31]:
float

Érdemes megjegyezni, hogy ez biztonsági résnek tekinthető, például

python
>>> intput()
exit()

Elágazás

In [32]:
x = input()
if x < 0:
    print "ez negatív"
elif x == 0:
    print "ez nulla"
elif x == 1:
    print "ez egy"
else:
    print "ez sok"
5
ez sok

Az elif-ek száma tetszőleges, de se az elif se az else megadása nem kötelező.

Ha az eredeti feltétel teljesül (igazra értékelődik), akkor az ő blokkjába eső (alatta behúzott) kód fut le, ha nem teljesül akkor az első olyan elif blokk fut le aminek a feltétele igaz, ha ezek se igazak akkor az else ág blokkja fut le, feltéve hogy van.

A behúzás (indentálás) legelterjedtebb mértéke a négy szóköz.

While ciklus

In [33]:
n = 1000
a = 1
while a ** 3 <= n:
    print a ** 3,  # a vessző miatt egy sorba kerülnek
    a = a + 1
print "vége"
1 8 27 64 125 216 343 512 729 1000 vége

A while ciklus blokkja lefut újra és újra, amíg teljesül a ciklus feltétele.

Így tehát a fenti kód addig növeli az a változót, amíg annak köbe legalább 1000 nem lesz.

Ciklusokat és elágazásokat egymásba ágyazhatunk:

A híres Collatz- vagy $3x+1$-probléma:

In [34]:
a = input()
while a != 1:
    print a,  # a vessző miatt egy sorba kerülnek
    if a % 2 == 0:
        a = a / 2
    else:
        a = a * 3 + 1
10
10 5 16 8 4 2

Ezt megtehetjük akárhány mélységig (ciklusok is ágyazhatók egymásba):

In [35]:
a = input()
if type(a) == int:
    while a != 1:
        print a,  # a vessző miatt egy sorba kerülnek
        if a % 2 == 0:
            a = a / 2
        else:
            a = a * 3 + 1
else:
    print "Egesz szamot adjunk meg"
10.1
Egesz szamot adjunk meg

A fenti kód már azt is teszteli, hogy a felhasználó egész számot adott-e meg. Védjük ki azt is, ha negatív számot adott meg:

In [36]:
a = input()
if type(a) == int:
    if a < 0:
        a = -1 * a
    while a != 1:
        print a,  # a vessző miatt egy sorba kerülnek
        if a % 2 == 0:
            a = a / 2
        else:
            a = a * 3 + 1
else:
    print "Egesz szamot adjunk meg"
-5
5 16 8 4 2

Végül már csak a 0 alesetet kell kizárni, hisz 0-ra se működik:

In [37]:
a = input()
if type(a) == int and a != 0:
    if a < 0:
        a = -1 * a
    while a != 1:
        print a,  # a vessző miatt egy sorba kerülnek
        if a % 2 == 0:
            a = a / 2
        else:
            a = a * 3 + 1
else:
    print "Nullatol kulonbozo egesz szamot adjunk meg"
0
Nullatol kulonbozo egesz szamot adjunk meg

Break

Ciklusokban használható a break utasítás, hogy a feltételt figyelmen kívül hagyva azonnal kiugorjunk a ciklusból:

In [38]:
n = input("Adj meg egy negyzetszamot 10000 alatt! ")
a = 0
while a ** 2 < 10000:
    if a ** 2 == n:
        break
    a = a + 1
if a ** 2 < 10000:
    print "A négyzetszám gyöke: %d" % a
else:
    print "Hazudtál! :("
Adj meg egy negyzetszamot 10000 alatt! 100
A négyzetszám gyöke: 10

Ha több ciklus van egymásba ágyazva, akkor a legbelső ciklusból ugrik ki, melynek blokkjában van.