Itt vagy: Kezdőlap Ugorj fejest a Python 3-ba

Nehézségi szint: ♦♢♢♢♢

Az első Python programod

Ne temesd terhed a szentek némaságába. Problémád van? Nagyszerű. Örvendj, merülj el, és vizsgálódj.
Ven. Henepola Gunaratana

 

Ugorj fejest

A megállapodás előírja, hogy a programozás alapvető építőköveivel kell untassalak, hogy lassan felépíthessünk valami hasznosat. Hagyjuk ezt ki. Ez itt egy teljes, működő Python program. Valószínűleg semmi értelme nincs számodra. Ne aggódj emiatt, hamarosan sorról sorra felboncoljuk. De előtte olvasd el, és próbálj meglátni benne valami értelmet.

[a humansize.py letöltése]

SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
            1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}

def approximate_size(size, a_kilobyte_is_1024_bytes=True):
    '''Egy fájlméret emberek által olvasható formába konvertálása.

    Kulcsszó argumentumok:
    size -- a fájlméret bájtban
    a_kilobyte_is_1024_bytes -- ha True (alapértelmezett), akkor az 1024 többszöröseit használja
                                ha False, akkor az 1000 többszöröseit használja

    Visszaad: karakterláncot

    '''
    if size < 0:
        raise ValueError('a szám nem lehet negatív')

    multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
    for suffix in SUFFIXES[multiple]:
        size /= multiple
        if size < multiple:
            return '{0:.1f} {1}'.format(size, suffix)

    raise ValueError('a szám túl nagy')

if __name__ == '__main__':
    print(approximate_size(1000000000000, False))
    print(approximate_size(1000000000000))

Most futtassuk ezt a programot a parancssorban. Windowson ez valahogy így néz ki:

c:\Documents and Settings\te\diveintopython3\examples> c:\python32\python.exe humansize.py 1.0 TB
931.3 GiB

Mac OS X vagy Linux alatt valahogy így fog kinézni:

te@localhost:~/diveintopython3/examples$ python3 humansize.py
1.0 TB
931.3 GiB

Mi történt? Végrehajtottad az első Python programod. Meghívtad a Python parancsértelmezőt a parancssorból, és átadtad neki annak a parancsfájlnak a nevét, amelyet a Pythonnal futtatni akartál. A parancsfájl egyetlen függvényt, az approximate_size() függvényt hívja meg, amely egy bájtban megadott pontos fájlméretet kap, és kiszámít egy „szép” (de közelítő) méretet. (Ezt valószínűleg láttad már a Windows Intézőben, vagy a Mac OS X Finderben, vagy Linuxon a Nautilusban, a Dolphinban vagy a Thunarban. Ha egy dokumentumokat tartalmazó mappát többoszlopos listaként jelenít meg, akkor a táblázatban a dokumentum ikonja, neve, mérete, típusa, legutóbbi módosítás dátuma stb. jelenik meg. Ha a mappa egy 1093 bájtos TODO nevű fájlt tartalmaz, akkor a fájlkezelő a TODO 1093 bájt helyett valami olyasmit fog kiírni, hogy TODO 1 KB. Ezt csinálja az approximate_size() függvény is.)

Nézd meg a parancsfájl alját, itt a print(approximate_size(argumentumok)) függvény két hívását láthatod. Ezek függvényhívások – először az approximate_size() függvényt hívják meg, átadva néhány argumentumot, majd a visszatérési értéket azonnal átadják a print() függvénynek. A print() függvény beépített, soha nem fogod az explicit deklarációját látni. Egyszerűen használhatod, bármikor, bárhol. (Rengeteg beépített függvény van, és annál is több van modulokba szervezve. Türelem, prücsök.)

Miért adja a parancssorból futtatott parancsfájl mindig ugyanazt a kimenetet? Azt is megnézzük. Először nézzük azonban az approximate_size() függvényt.

Függvények deklarálása

A Python a legtöbb nyelvhez hasonlóan rendelkezik függvényekkel, de nincsenek önálló fejlécfájlok, mint a C++-ban vagy interfész/megvalósítás szakaszok, mint a Pascalban. Ha egy függvényre van szükséged, egyszerűen csak deklaráld, így:

def approximate_size(size, a_kilobyte_is_1024_bytes=True):

A def kulcsszó elindítja a függvénydeklarációt, amelyet a függvény neve és zárójelek közt a paraméterek követnek. Több paraméter vesszőkkel választható el.

Vedd észre, hogy a függvény nem definiál visszatérési adattípust. A Python függvények nem adják meg a visszatérési értékük adattípusát, sőt azt sem, hogy egyáltalán visszaadnak-e értéket. (Valójában minden Python függvény visszaad egy értéket; ha a függvény végrehajt egy return utasítást, akkor annak értékét adja vissza, ellenkező esetben a None értéket, a Python nullértékét.

Egyes nyelvekben (az értéket visszaadó) függvények a function, míg a szubrutinok (amelyek nem adnak vissza értéket) a sub kulcsszóval kezdődnek. Pythonban nincsenek szubrutinok. Minden függvény, minden funkció visszaad egy értéket (még ha az a None is), és minden függvény a def kulcsszóval kezdődik.

Az approximate_size() függvény két – a size és a_kilobyte_is_1024_bytes – paramétert vár, de egyik paraméter sem ad meg adattípust. Pythonban a változók soha nem kifejezetten típusosak. A Python meghatározza a változó típusát, és azt saját maga tartja nyilván.

Java és más statikusan típusos nyelveknél meg kell adnod a függvény visszatérési értékének és minden egyes függvényparaméter adattípusát. Pythonban soha nem kell kifejezetten megadni semminek az adattípusát. A hozzárendelt érték alapján a Python saját maga tartja nyilván az adattípust.

Elhagyható és nevesített argumentumok

A Python lehetővé teszi, hogy a függvényparaméterek alapértelmezett értékkel rendelkezzenek, ha a függvény argumentum nélkül kerül meghívásra, akkor az argumentum az alapértelmezett értéket kapja. Ezen kívül az argumentumok tetszőleges sorrendben is megadhatók nevesített argumentumok használatával.

Vessünk egy újabb pillantást az approximate_size() függvény deklarációjára:

def approximate_size(size, a_kilobyte_is_1024_bytes=True):

A második paraméter, az a_kilobyte_is_1024_bytes megad egy alapértelmezett értéket, ez a True. Ez azt jelenti, hogy a paraméter elhagyható; a függvény meghívható nélküle is, és a Python úgy fog viselkedni, mintha a második paramétere a True lett volna.

Most nézd meg a parancsfájl alját:

if __name__ == '__main__':
    print(approximate_size(1000000000000, False))  
    print(approximate_size(1000000000000))         
  1. Ez az approximate_size() függvényt két argumentummal hívja meg. Az approximate_size() függvényen belül az a_kilobyte_is_1024_bytes értéke False lesz, mivel második argumentumként a False értéket adjuk át.
  2. Ez az approximate_size() függvényt csak egy argumentummal hívja meg. De ez nem gond, mivel a második argumentum elhagyható! Mivel a hívó nem adja meg, a második argumentum az alapértelmezett True értéket kapja meg, ahogyan az a függvény deklarációjában meg van határozva.

A függvénynek név szerint is átadhatsz értékeket.

>>> from humansize import approximate_size
>>> approximate_size(4000, a_kilobyte_is_1024_bytes=False)       
'4.0 KB'
>>> approximate_size(size=4000, a_kilobyte_is_1024_bytes=False)  
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, size=4000)  
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, 4000)       
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> approximate_size(size=4000, False)                           
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
  1. Ez az approximate_size() függvényt a 4000 első argumentummal (size) hívja meg, és a False értékkel az a_kilobyte_is_1024_bytes paraméterhez. (Ez most a második argumentum, de nem számít, ahogy mindjárt látni fogod.)
  2. Ez az approximate_size() függvényt a 4000 argumentummal hívja meg a size paraméterhez, és a False értékkel az a_kilobyte_is_1024_bytes paraméterhez. (Ezek a nevesített argumentumok ugyanabban a sorrendben vannak felsorolva, mint a függvénydeklarációban, de ez sem számít.)
  3. Ez az approximate_size() függvényt a False értékkel hívja meg az a_kilobyte_is_1024_bytes nevű paraméterhez, és a 4000 értékkel a size nevű paraméterhez. (Látod? Megmondtam, hogy a sorrend nem számít.)
  4. Ez a hívás meghiúsul, mert egy nevesített argumentumot egy nem nevesített (helyzeti) argumentum követ, és ez soha nem működik. Ha az argumentumlistát balról jobbra olvasod, akkor egy nevesített argumentumot követően a többi argumentumnak is nevesítettnek kell lennie.
  5. Ez a hívás is meghiúsul, ugyanazért, amiért az előző. Meglepő? Végül is, a 4000 értéket a size nevű paraméternek adtad át, „nyilvánvaló”, hogy a False értéket az a_kilobyte_is_1024_bytes paraméternek szántad. De a Python nem így működik. Amint van egy nevesített argumentumod, attól jobbra minden argumentumnak nevesítettnek kell lennie.

Olvasható kód írása

Nem foglak hosszú hegyibeszéddel untatni a kódod dokumentálásának fontosságáról. Azt tartsd észben, hogy a kódot egyszer írják, de sokszor olvassák, és a kódod legfontosabb közönsége te vagy, hat hónappal a megírása után (azaz amikor már mindent elfelejtettél, de valamit ki kell javítanod). A Python egyszerűvé teszi az olvasható kód írását, használd ezt ki. Hat hónap múlva meg fogod köszönni.

Dokumentációs karakterláncok

A Python függvényeket egy dokumentációs karakterlánc (röviden és angolul docstring) megadásával dokumentálhatod. Ebben a programban az approximate_size() függvénynek van docstring-je:

def approximate_size(size, a_kilobyte_is_1024_bytes=True):
    '''Egy fájlméret emberek által olvasható formába konvertálása.
    Kulcsszó argumentumok:
    size -- a fájlméret bájtban
    a_kilobyte_is_1024_bytes -- ha True (alapértelmezett), akkor az 1024 többszöröseit használja
                                ha False, akkor az 1000 többszöröseit használja
    Visszaad: karakterláncot

    '''

A három idézőjel többsoros karakterláncot jelez. A kezdő és záró idézőjelek között minden egyetlen karakterlánc része, beleértve a sortöréseket, a kezdő üres helyeket és más idézőjel karaktereket. Ezeket bárhol használhatod, de leggyakrabban a docstring megadásakor láthatod őket.

A három idézőjel segítségével egyszerűen adhatsz meg olyan karakterláncot, amely egyszeres és dupla idézőjelet is tartalmaz, a Perl 5 qq/.../ kulcsszavához hasonlóan.

A három idézőjelen belül minden a függvény docstring-je, amely a függvény működését dokumentálja. A docstring-et, ha van, a függvényben elsőként kell megadni (azaz a függvénydeklaráció utáni sorban). Technikailag nem kötelező a függvényhez docstring-et megadnod, de jobban jársz a megadásával. Tudom, hogy ezt minden programozás órán elmondták, de a Python további motivációt ad: a docstring futás közben a függvény attribútumaként is elérhető.

Sok Python IDE a docstring-et használja helyzetérzékeny dokumentáció biztosítására, így amikor beírod egy függvény nevét, a hozzá tartozó docstring megjelenik a buboréksúgóban. Ez hihetetlenül hasznos tud lenni, de csak annyira, amennyire az általad írt docstring-ek.

Az import keresési útvonala

Mielőtt továbbmegyünk, röviden szeretném megemlíteni a függvénytárak keresési útvonalát. A Python több helyen is keresi az importálni kívánt modulokat. Pontosabban, a sys.path által meghatározott könyvtárakban. Ez csak egy lista, és egyszerűen megjelenítheted vagy módosíthatod a szabványos listakezelési módszerekkel. (A listákról a Natív adattípusok fejezetben tudhatsz meg többet.)

>>> import sys                                                 
>>> sys.path                                                   
['',
 '/usr/lib/python32.zip',
 '/usr/lib/python3.2',
 '/usr/lib/python3.2/plat-linux2@EXTRAMACHDEPPATH@',
 '/usr/lib/python3.2/lib-dynload',
 '/usr/lib/python3.2/dist-packages',
 '/usr/local/lib/python3.2/dist-packages']
>>> sys                                                        
<module 'sys' (built-in)>
>>> sys.path.insert(0, '/home/mark/diveintopython3/examples')  
>>> sys.path                                                   
['/home/mark/diveintopython3/examples',
 '',
 '/usr/lib/python32.zip',
 '/usr/lib/python3.2',
 '/usr/lib/python3.2/plat-linux2@EXTRAMACHDEPPATH@',
 '/usr/lib/python3.2/lib-dynload',
 '/usr/lib/python3.2/dist-packages',
 '/usr/local/lib/python3.2/dist-packages']
  1. A sys modul importálása minden függvényét és attribútumát elérhetővé teszi.
  2. A sys.path könyvtárnevek listája, amelyek az aktuális keresési útvonalat alkotják. (A tiéd másképp fog kinézni, függően az operációs rendszeredtől, a Python verziójától, és annak eredeti telepítési helyétől.) A Python ezekben a könyvtárakban fogja keresni (ebben a sorrendben) azt a .py fájlt, amelynek neve megegyezik azzal, amit importálni próbálsz.
  3. Valójában hazudtam. Az igazság ennél bonyolultabb, mert nem minden modul van .py fájlokként tárolva. Egyes modulok beépítettek; valójában bele vannak drótozva magába a Pythonba. A beépített modulok úgy viselkednek, mint a normális modulok, de a Python forráskódjuk nem érhető el, mivel nem Pythonban vannak írva! (Mint maga a Python, ezek a beépített modulok is C-ben íródtak.)
  4. Futási időben új könyvtárat adhatsz a Python keresési útvonalához a könyvtárnév sys.path-hoz adásával, ezután a Python abban a könyvtárban is keresni fogja az importált modulokat. Ennek hatása addig tart, amíg a Python értelmező fut.
  5. A sys.path.insert(0, új_útvonal) használatával beszúrtál egy új könyvtárat a sys.path lista első elemeként, emiatt a Python keresési útvonalának elejére. Majdnem mindig ezt szeretnéd. Elnevezési ütközések esetén (ha például a Python egy adott függvénytár 2-es verzióját szállítja, de a 3-as verziót szeretnéd használni), akkor ez biztosítja, hogy a moduljaidat a Python a beépített modulok előtt találja meg és használja.

Minden objektum

Ha elsiklottál volna fölötte, akkor az előbb azt mondtam, hogy a Python függvényeknek attribútumaik vannak, és azok az attribútumok futás közben elérhetők. A függvények, mint minden más is Pythonban, objektumok.

Indítsd el az interaktív Python parancsértelmezőt, és próbáld ki ezt:

>>> import humansize                               
>>> print(humansize.approximate_size(4096, True))  
4.0 KiB
>>> print(humansize.approximate_size.__doc__)      
Egy fájlméret emberek által olvasható formába konvertálása.

    Kulcsszó argumentumok:
    size -- a fájlméret bájtban
    a_kilobyte_is_1024_bytes -- ha True (alapértelmezett), akkor az 1024 többszöröseit használja
                                ha False, akkor az 1000 többszöröseit használja
    Visszaad: karakterláncot

  1. Az első sor a humansize programot modulként importálja – ez egy olyan kóddarab, amelyet interaktívan vagy egy nagyobb Python programból is használhatsz. Egy modul importálása után bármely nyilvános függvényére, osztályára vagy attribútumára hivatkozhatsz. A modulok ezzel elérhetik más modulok funkcionalitását, és ezt a Python interaktív parancsértelmezőjéből te is megteheted. Ez egy fontos fogalom, és rengetegszer fogod látni ebben a könyvben.
  2. Amikor az importált modulokban definiált függvényeket akarod használni, akkor a modulnevet is használnod kell. Emiatt nem hivatkozhatsz az approximate_size függvényre; hanem csak a humansize.approximate_size függvényre. Ha használtál osztályokat Javaban, akkor ez nagyjából ismerős kell legyen.
  3. A függvény hívása helyett az egyik attribútumát, a __doc__-ot kéred le.

Az import Pythonban olyan, mint a require Perlben. Az import használatával beágyazott Python modult függvényeit modul.függvény formában érheted el; a require használatával beágyazott Perl modul függvényeit a modul::függvény formában érheted el.

Mi az az objektum?

Pythonban minden objektum, és mindennek lehetnek attribútumai és metódusai. Minden függvénynek van egy beépített __doc__ nevű attribútuma, amely a függvény forráskódjában definiált docstring értékét adja vissza. A sys modul egy objektum, amely rendelkezik (többek között) egy path nevű attribútummal. És így tovább.

Ez azonban még mindig nem válaszolja meg az alapkérdést: mi az az objektum? A különböző programozási nyelvek különbözőképpen definiálják az „objektum” fogalmát. Egyesekben ez azt jelenti, hogy minden objektumnak rendelkeznie kell attribútumokkal és metódusokkal, másokban azt jelenti, hogy minden objektumból származtatható osztály. Pythonban a definíció lazább. Egyes objektumoknak nincsenek sem attribútumai, sem metódusai, de lehetne nekik. Nem minden objektumból származtathatók osztályok. De minden objektum abban az értelemben, hogy változóhoz rendelhetők, vagy átadhatók egy függvény argumentumaként.

Más programozási nyelvek kapcsán hallhattad az „első osztályú objektum” kifejezést. Pythonban a függvények első osztályú objektumok. Egy függvény átadható argumentumként egy másik függvénynek. A modulok első osztályú objektumok. Egy egész modult átadhatsz argumentumként egy függvénynek. Az osztályok első osztályú objektumok, és az osztályok egyes példányai is első osztályú objektumok.

Ez fontos, ezért megismétlem, ha az első néhány alkalommal lemaradtál róla: Pythonban minden objektum. A karakterláncok objektumok. A listák objektumok. A függvények objektumok. Az osztályok objektumok. Az osztálypéldányok objektumok. Még a modulok is objektumok.

Kódbehúzás

A Python függvények nem rendelkeznek explicit kezdettel vagy véggel, és nem jelöli kapcsos zárójel a függvények kezdetét és végét. Az egyetlen határoló a kettőspont (:) és maga a kódbehúzás.

def approximate_size(size, a_kilobyte_is_1024_bytes=True):  
    if size < 0:                                            
        raise ValueError('a szám nem lehet negatív')     
                                                            
    multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
    for suffix in SUFFIXES[multiple]:                       
        size /= multiple
        if size < multiple:
            return '{0:.1f} {1}'.format(size, suffix)

    raise ValueError('a szám túl nagy')
  1. A kódblokkokat a behúzásuk határozza meg. A „kódblokk” alatt függvényeket, if utasításokat, for ciklusokat, while ciklusokat és hasonlókat értek. A behúzás elkezdi a blokkot, és a behúzás vége befejezi. Nincsenek explicit kapcsos zárójelek, szögletes zárójelek vagy kulcsszavak. Ez azt jelenti, hogy az üres helynek jelentősége van, és konzisztensnek kell lennie. Ebben a példában a függvény kódját négy szóköz húzza be. Nem kell mindig négy szóköznek lennie, csak konzisztensnek. Az első sor, amely nincs behúzva, jelzi a függvény végét.
  2. Pythonban az if utasítást egy kódblokk követi. Ha az if kifejezés értéke igaz, akkor a behúzott blokk kerül végrehajtásra, ellenkező esetben az else blokk (ha van). Vedd észre a zárójelek hiányát a kifejezés körül.
  3. Ez a sor az if kódblokkon belül van. Ez a raise utasítás egy (ValueError típusú) kivételt fog dobni, de csak ha a size < 0.
  4. Ez nem a függvény vége. A teljesen üres sorok nem számítanak. Ezek olvashatóbbá tehetik a kódot, de nem számítanak kódblokkhatárolónak. A függvény a következő sorban folytatódik.
  5. A for ciklus is a kódblokk kezdetét jelzi. A kódblokkok több sort is tartalmazhatnak, amíg ugyanannyival vannak behúzva. Ez a for ciklus három sort tartalmaz. A többsoros kódblokkoknak nincs speciális szintaxisuk. Csak húzd be őket, és haladj.

Némi kezdeti tiltakozás és rosszindulatú Fortranhoz hasonlítgatás után meg fogsz ezzel békülni, és elkezded látni az előnyeit. Az egyik nagy előnye, hogy minden Python program hasonlóan néz ki, mert a behúzás a nyelv követelménye, és nem stílus kérdése. Ez egyszerűbbé teszi mások Python kódjának olvasását és megértését.

A Python sortöréseket használ az utasítások elválasztására, és kettőspontot és behúzást a kódblokkok elválasztására. A C++ és Java pontosvesszőket használnak az utasítások elválasztására, és kapcsos zárójeleket a kódblokkok elválasztására.

Kivételek

A Python tele van kivételekkel. Gyakorlatilag a szabványos függvénytár minden modulja használja ezeket, és maga a Python is rengeteg különböző helyzetben dob kivételeket. A könyvben újra és újra találkozni fogsz velük.

Mi az a kivétel? Általában egy hiba, azt jelzi, hogy valami nem sikerült. (Nem minden kivétel hiba, de egyelőre ezzel ne foglalkozz.) Egyes programozási nyelvek a visszatérési kódok használatát bátorítják, amelyeket ellenőrizhetsz. A Python a kivételek használatát bátorítja, amelyeket kezelhetsz.

Amikor hiba történik a Python parancsértelmezőben, akkor kiír néhány részletet a kivételről és a bekövetkezésének körülményeiről, és ennyi. Ezt kezeletlen kivételnek hívjuk. A kivétel dobásakor nem volt jelen kód az észrevételéhez és kezeléséhez, így az feljutott a Python parancsértelmező felső szintjére, amely kiköp némi hibakeresési információt, és ennyivel megoldottnak tekinti a problémát. A parancsértelmezőben ez nem gond, de ha egy tényleges Python program futása közben történt volna, akkor - hacsak valami nem kezeli a kivételt - az egész program összeomlott volna. Lehet, hogy ezt akarod, lehet, hogy nem.

A Javaval ellentétben a Python függvények nem deklarálják, hogy milyen kivételeket dobhatnak. Rád van bízva, hogy meghatározd, milyen esetleg bekövetkező kivételeket kell elkapnod.

Egy kivétel azonban nem okozza szükségszerűen a teljes program összeomlását. A kivételek kezelhetők. Néha egy kivétel csak a kódod hibáját jelzi (például nem létező változót próbálsz elérni), de néha a kivétel egy várható dolog. Amikor megnyitsz egy fájlt, akkor előfordulhat, hogy az nem létezik. Amikor importálsz egy modult, akkor előfordulhat, hogy az nincs telepítve. Amikor egy adatbázishoz csatlakozol, akkor előfordulhat, hogy az nem érhető el, vagy nincsenek megadva az eléréséhez szükséges hitelesítési adatok. Ha tudod, hogy egy kódsor kivételt dobhat, akkor azt a kivételt kezelned kell egy try...except blokkal.

A Python a try...except blokkokat használja a kivételek kezelésére, és a raise utasítást az előállításukra. A Java és a C++ a try...catch blokkokat használják a kivételek kezelésére, és a throw utasítást az előállításukra.

Az approximate_size() függvény két különböző esetben dob kivételt: ha a megadott size értéke nagyobb, mint aminek a kezelésére a függvény tervezve van, vagy ha az kisebb, mint nulla.

if size < 0:
    raise ValueError('a szám nem lehet negatív'')

A kivétel dobásának szintaxisa elég egyszerű. Add meg a raise utasítást, majd a kivétel nevét, és egy elhagyható, emberek által olvasható karakterláncot hibakeresési célokra. A szintaxis hasonlít egy függvény hívásához. (A valóságban a kivételek osztályokként vannak megvalósítva, és ez a raise utasítás példányosítja a ValueError osztályt, és átadja neki az 'a szám nem lehet negatív'' karakterláncot az inicializálási metódusában. De ezzel most előre szaladtam!)

A kivételt nem kötelező abban a függvényben kezelned, amely dobja. Ha egy függvény nem kezeli, akkor a kivétel átadásra kerül a hívó függvénynek, ezután annak a hívó függvényének és így tovább a „hívási láncon.” Ha a kivétel soha nem kerül kezelésre, akkor a program összeomlik, és a Python kiír egy „visszakövetést” a szabványos hibakimenetre, és ezzel vége. Ismétlem, lehet, hogy ezt akarod, attól függ, hogy mit csinál a programod.

Importálási hibák elkapása

A Python egyik beépített kivétele az ImportError, amelyet akkor dob, amikor megpróbálsz importálni egy modult, de az nem sikerül. Ez rengeteg okból bekövetkezhet, de a legegyszerűbb, hogy a modul nem létezik az import keresési útvonalán. Ezt elhagyható szolgáltatások felvételére használhatod a programodba. Például a chardet függvénytár a karakterkódolás automatikus felismerését nyújtja. Lehet, hogy a programod használni akarja ezt a könyvtárat, ha létezik, de akkor is elegánsan folytatódik, ha a felhasználó nem telepítette. Ezt egy try..except blokkal oldhatod meg.

try:
  import chardet
except ImportError:
  chardet = None

Később a chardet modul jelenlétét egy egyszerű if utasítással ellenőrizheted:

if chardet:
  # csinál valamit
else:
  # így is folytatódik

Az ImportError kivétel másik gyakori használati módja, amikor két modul valósít meg egy közös API-t, de az egyik valamiért jobb, mint a másik. (Például gyorsabb vagy kevesebb memóriát használ.) Megpróbálhatod importálni az egyik modult, de használhatsz egy másik modult, ha az első importálás meghiúsul. Az XML fejezet például két modulról beszél, amelyek megvalósítanak egy közös API-t, az ElementTree nevű API-t. Az első, az lxml egy külső modul, amelyet saját magadnak kell letöltened és telepítened. A második, az xml.etree.ElementTree lassabb, de része a Python 3 szabványos függvénytárának.

try:
    from lxml import etree
except ImportError:
    import xml.etree.ElementTree as etree

Ennek a try..except blokknak a végére importáltál egy modult, amit etree-nek nevezel. Mivel mindkét modul egy közös API-t valósít meg, a kódod többi részének nem kell folyton ellenőriznie, hogy melyik modul lett importálva. Mivel a ténylegesen importált modul neve mindig etree, a kódot nem kell teleszemetelni if utasításokkal, hogy más-más nevű modulokat hívjanak.

Nem kötött változók

Vessünk egy újabb pillantást az approximate_size() függvény ezen sorára:

multiple = 1024 if a_kilobyte_is_1024_bytes else 1000

A multiple változót sehol nem deklarálod, csak hozzárendelsz egy értéket. Ez rendben van, mert a Python lehetővé teszi. Amit a Python nem fog lehetővé tenni, az egy olyan változóra hivatkozás, amelyhez soha nem rendeltél értéket. Ha megpróbálod, akkor a Python egy NameError kivételt fog dobni.

>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> x = 1
>>> x
1

Egy napon ezt meg fogod köszönni a Pythonnak.

Minden megkülönbözteti a kis- és nagybetűket

A Pythonban minden név megkülönbözteti a kis- és nagybetűket: változónevek, függvénynevek, osztálynevek, modulnevek, kivételnevek. Ha le tudod kérdezni, be tudod állítani, meg tudod hívni, létre tudod hozni, importálni vagy dobni tudod, akkor megkülönbözteti a kis- és nagybetűket.

>>> egy_változó = 1
>>> egy_változó
1
>>> EGY_VÁLTOZÓ
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'EGY_VÁLTOZÓ' is not defined
>>> Egy_Változó
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Egy_Változó' is not defined
>>> egy_válTozó
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'egy_válTozó' is not defined

És így tovább.

Parancsfájlok futtatása

A Python modulok objektumok, és számos hasznos attribútummal rendelkeznek. Ezt a moduljaid egyszerű tesztelésére használhatod azok írása közben. Csak vegyél fel egy speciális blokkot, amely lefut a Python fájl parancssorban való futtatásakor. Vegyük a humansize.py utolsó néhány sorát:


if __name__ == '__main__':
    print(approximate_size(1000000000000, False))
    print(approximate_size(1000000000000))

A C-hez hasonlóan a Python is az == operátort használja az összehasonlításra, és az = operátort az értékadásra. A C-vel szemben a Python nem támogatja a beágyazott értékadást, így nem tudod véletlenül hozzárendelni azt az értéket, amelyet össze akartál hasonlítani.

Akkor mi teszi ezt az if utasítást olyan különlegessé? Nos, a modulok objektumok, és minden modulnak van egy beépített __name__ attribútuma. A modul __name__ attribútumának értéke attól függ, hogyan használod a modult. Ha import utasítással importálod a modult, akkor a __name__ értéke a modul fájlneve lesz, könyvtárelérési út vagy fájlkiterjesztés nélkül.

>>> import humansize
>>> humansize.__name__
'humansize'

A modult azonban közvetlenül is futtathatod önálló programként, ebben az esetben a __name__ egy speciális alapértelmezett értéket kap, ez a __main__. A Python kiértékeli ezt az if utasítást, igaz kifejezést talál, és végrehajtja az if kódblokkját. Ebben az esetben két értéket ír ki.

c:\home\diveintopython3> c:\python32\python.exe
humansize.py 1.0 TB
931.3 GiB

És ez volt az első Python programod!

További olvasnivaló

© 2001–11 Mark Pilgrim