Python az iskolában Wiki

A Python típusosságának négy fő jellemzője: erős, dinamikus, objektumorientált és „kacsatípusos”.

A Python erősen típusos[]

Az erős típusosság fogalma az irodalomban nem egységes. A Python abban az értelemben erősen típusos, hogy kerüli az implicit típuskonverziókat, és rákényszeríti a programozót, hogy ő maga végezze el ezt a munkát. A hármas verzió egyik célja ennek a szigorúságnak az erősítése; így például még a „text”-nek nevezett Unicode-stringek és a „data”-nak nevezett, 8 bites karakterekből álló láncok konkatenálását sem engedi meg explicit típuskonverzió nélkül.

A típuskeverés – akár értékadásban, akár feltételvizsgálatban – futásidejű hibát okoz, amely kivételként kezelhető (lásd a példát a következő szakaszban). Valószínűbb azonban, hogy a hibaüzenet programozási hibát jelez, és inkább az okát kell átgondolni.

A Python dinamikusan tipizál[]

A dinamikus típusosság azt jelenti, hogy nem a változónak, hanem az értéknek van típusa, amit az értelmező futásidőben állapít meg. Nem kell előre deklarálni a felhasznált változók típusát, mint a Pascalban vagy a C-ben. Ez nagyobb rugalmasságot tesz lehetővé, de nagyobb fegyelmet is igényel. A szigorú típusosságnak köszönhetően azonban hamar a körmünkre koppint az értelmező, ha összekeverünk valamit.

Az alábbi példában az a változó előbb egész értéket kap, amihez hozzá tudunk adni hármat, majd string értéket, amitől megváltozik a típusa. Ha most próbáljuk elvégezni az összeadást, TypeError kivételt kapunk. (A parancssor egyúttal számológépként is működik, tetszőleges kifejezést beírva megkapjuk az értékét, ezért a print() függvény használata itt mellőzhető. Ne lepődjünk meg a megváltozott idézőjelen, a Python egyformán felismeri mind a kettőt.)

>>> a=5
>>> a+3
8
>>> a="5"
>>> a
'5'
>>> a+3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

Ezután gépeljük be a parancssori promptnál az alábbi kivételkezelő kódot. Úgy írhatunk, mintha programot írnánk, figyelve a behúzásokra. A prompt a kódbeírást érzékelve megváltozik ...-ra. Az utolsó sorban enterrel jelezzük, hogy befejeztük a bevitelt, mire megkapjuk a helyes eredményt, immáron stringként.

>>> try:
...   a+3
... except TypeError:
...   a+"3"
...
'53'

Sőt, akár az alábbi mókát is megengedhetjük magunknak:

>>> b="4"
>>> c=7
>>> a+c*b
'54444444'

Az a+c*b kifejezésről tehát nem tudjuk megmondani, hogy összeadást vagy konkatenációt fejez-e ki, amíg nem ismerjük a változók aktuális típusát. Sőt, mivel a függvényparaméterek típusa is ugyanilyen dinamikus, még az alábbi függvény is az átadott paraméterek típusától függően viselkedik:

>>> def valami (a,b,c):
...  return(a+c*b)
...
>>> a="5"
>>> b="4"
>>> c=7
>>> valami(a,b,c)
'54444444'
>>> b=3
>>> c="9"
>>> valami(a,b,c)
'5999'
>>> a=2
>>> c=7
>>> valami(a,b,c)
23

Ez talán egy kicsivel nagyobb rugalmasság, mint amit kezdő tanítványoknak szeretnénk nyújtani, de hamar meg lehet szokni, és – főleg, ha beszédes változónevekkel kombináljuk – nem akadálya a gondolati tisztaságnak és a strukturált programozásnak. Másrészt a dinamikus típusosság úgy tesz lehetővé memóriafoglalást a futásidőben, hogy feleslegessé válik a kezdő C- és C++-programozók életét megkeserítő mutatók használata.

Ugyanez a furcsaság gondot okozhat az adatbevitelben (akár a billentyűzetről, akár file-ból), ha nem figyelünk. Mivel az adatbevitel nem kötődik előre deklarált típushoz – sőt, mint a példa mutatja, még változóhoz sem feltétlenül! –, ezért a típusa sem magától értetődő. (Természetesen az alábbi tömör írásmódot csak akkor használhatjuk, ha nem akarjuk tárolni a beolvasott értéket. A C-stílusú, „röptében” történő értékadást a zárójelen belül a Python szándékosan nem engedi.)

>>> print('A háromszorosa:',3*input('Kérem a számot: '))
Kérem a számot: 7
A háromszorosa: 777

Nem nehéz rájönni, mi történt: az értelmező szövegként kezeli a bevitt adatot. Akár rejtvényként is feladhatjuk tanítványainknak a magyarázatot. Explicit kiírással is meggyőződhetünk róla:

>>> b=input('A szám: ')
A szám: 5
>>> b
'5'

A megoldás mind a billentyűzetről, mind a lemezről beolvasott számok esetében az int() konvertálófüggvény használata:

>>> print('A háromszorosa:',3*int(input('Kérem a számot: ')))
Kérem a számot: 7
A háromszorosa: 21

Vigyáznunk kell azonban, mert az int() a nem numerikus adatoktól rögtön megadja magát!

>>> print('A háromszorosa:',3*int(input('Kérem a számot: ')))
Kérem a számot: lajos
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'lajos'

Ez a hiba könnyen kezelhető, azonban ez már a kivételkezelésről szóló szócikk témája.

A Python típusai egyúttal osztályok is[]

A Verziók felismerése és átalakítása szócikkben azt láthatjuk a képeken, hogy a type() függvény a 2.5 verzióban a „type”, a 3.1 verzióban a „class” szót adja vissza a változó típusa előtt. Minden típus egyúttal osztály is. A kezdő programozónak nem kell ezzel törődnie, tehát leérettségizhet az objektumok ismerete nélkül is.

A típusok ilyetén kezelése két fő előnnyel jár:

  • Az egyes típusokhoz kényelmesen használható beépített metódusok tartozhatnak. Lásd a példát a Paradigmák cikkben.
  • A beépített típusokból kedvünk szerint hozhatunk létre származtatott típusokat, amelyek öröklik a szülőtípus tulajdonságait és metódusait. Részletesen, példával lásd Guido van Rossum cikkében:

Duck typing[]

Megírandó, addig lásd itt.

Ez a szócikk forráskódot tartalmaz, amely egy WikiMedia-kiegészítés segítségével olyan színesen jeleníthető meg, mint például ebben a Wikipédia-cikkben. A kiegészítést a Wikia-stáb ígérete szerint 2010 végéig frissítik, addig türelmet kérünk a fapados kinézet miatt.