Informatika2-2015/Eloadas 3 Python-3 Opcionalis parameter Dokumentacio

A MathWikiből
(Változatok közti eltérés)
a (Dosctring)
 
148. sor: 148. sor:
  
 
A python-ban sztenderd módszer a modulok dokumentálására a [http://www.python.org/dev/peps/pep-0257/ docstring]. Az első sornak egy mondatos összefoglalónak kell lennie, ponttal lezárva. (Van olyan alkalom amikor csak ez a sor jelenik meg.) A többi szabad formájú. Általában érdemes a paramétereket és a visszatérési értéket dokumentálni, ha lehet velük bármi meglepő.
 
A python-ban sztenderd módszer a modulok dokumentálására a [http://www.python.org/dev/peps/pep-0257/ docstring]. Az első sornak egy mondatos összefoglalónak kell lennie, ponttal lezárva. (Van olyan alkalom amikor csak ez a sor jelenik meg.) A többi szabad formájú. Általában érdemes a paramétereket és a visszatérési értéket dokumentálni, ha lehet velük bármi meglepő.
 +
 +
A példafüggvény így néz ki ilyen egyszerű docstring-el (de akár az első sor is elég lehetne):
 +
 +
<python>ponthatar = 40
 +
 +
def atment(pontok, hatar = ponthatar, sorban = True):
 +
    """
 +
    Visszaadja egy listaban hogy mely hallgatok mentek at egy ZHn.
 +
 +
    Parameterek:
 +
        pontok: a hallgatok pontjai, szotarban, ami a nevhez pontot rendel.
 +
        hatar: akkor ment at ha ennel nagyobb vagy egyenlo a pontja.
 +
    """
 +
    nevek = [nev for nev in pontok if pontok[nev] >= hatar]
 +
    if sorban:
 +
        nevek.sort()
 +
    return nevek</python>
  
 
Az így megírt docstring-et a python beépítve tudja használni, pl. a '''help''' paranccsal. Vagy, a python egyik beépített könyvtára HTML honlapot is tud belőle generálni. Valahogy így:
 
Az így megírt docstring-et a python beépítve tudja használni, pl. a '''help''' paranccsal. Vagy, a python egyik beépített könyvtára HTML honlapot is tud belőle generálni. Valahogy így:
  d:\Python27\Lib\pydoc.py -w atment
+
  <python_helye>\Python27\Lib\pydoc.py -w atment
 +
Linux-on elég annyi hogy
 +
pydoc -w atment
  
 
== Tesztelésről általában ==
 
== Tesztelésről általában ==

A lap jelenlegi, 2015. március 4., 02:41-kori változata

Tartalomjegyzék

Opcionális paraméterek

Python függvények definiálásánál megadhatóak úgynevezett opcionális paraméterek. Ilyent akkor használunk, ha van egy olyan paramétere a függvénynek, ami fontos hogy paraméter legyen, mert időnként megváltoztatjuk, de az esetek túlnyomó többségében ugyanaz az értéke. Ilyenkor adhatunk a paraméternek egy alapértelmezett értéket, és ha a függvényhíváskor azt a paramétert nem kapja meg a függvény, akkor az alapértelmezett értéket használja. Például:

>>> def atment(pontok, hatar = 40, sorban = True):
...     nevek = [nev for nev in pontok if pontok[nev] >= hatar]
...     if sorban:
...         nevek.sort()
...     return nevek
...
>>> erdei_pontok = {
...     "Roka" : 85,
...     "Medve" : 20,
...     "Nyuszi" : 95,
...     "Farkas" : 45,
...     "Suni" : 55}
>>> print atment(erdei_pontok, 10, False)
['Medve', 'Farkas', 'Nyuszi', 'Suni', 'Roka']
>>> print atment(erdei_pontok)
['Farkas', 'Nyuszi', 'Roka', 'Suni']
>>> print atment(erdei_pontok, 10)
['Farkas', 'Medve', 'Nyuszi', 'Roka', 'Suni']

Mint látható, kihagyható az összes opcionális paraméter, vagy csak néhány.

Előfordulhat viszont, hogy csak a későbbi paramétert akarjuk megadni, a korábbit nem. Ezért találták ki a név szerinti paraméter átadást:

>>> print atment(erdei_pontok, hatar=10, sorban=False)
['Medve', 'Farkas', 'Nyuszi', 'Suni', 'Roka']
>>> print atment(erdei_pontok, sorban=False)
['Farkas', 'Nyuszi', 'Suni', 'Roka']

Sőt, ha akarjuk, a normális ("kötelező") paramétereket is adhatjuk át így név szerint (a másik módszert úgy hívják, hogy pozíció szerint):

>>> print atment(pontok=erdei_pontok)
['Farkas', 'Nyuszi', 'Roka', 'Suni']
Python Tutor link

Másik előnye a név szerinti megadásnak, hogy elég annak a paraméternek a nevére emlékezni amit meg akarunk adni. Például ha megnézzük a beépített könyvtárban a pprint függvényt, elég sok paramétere van, ezek közül a stream pl. olyan dologgal foglalkozik amit még nem tanultunk. Azonban elég ha a width paramétert megértjük ahhoz hogy azt használni tudjuk.

>>> import pprint
>>> pprint.pprint(erdei_pontok)
{'Farkas': 45, 'Medve': 20, 'Nyuszi': 95, 'Roka': 85, 'Suni': 55}
>>> pprint.pprint(erdei_pontok, width=20)
{'Farkas': 45,
 'Medve': 20,
 'Nyuszi': 95,
 'Roka': 85,
 'Suni': 55}

Azért néhány korlátozás van:

  • Logikusan, csak az opcionális paramétereket lehet elhagyni, minden normális paraméternek értéket kell adni, vagy név szerint, vagy pozíció szerint.
  • Ha név szerint és pozició szerint is akarunk megadni paramétert, mindenképpen előbb kell a pozició szerintieknek lennie. Ez nem megengedett:
>>> print atment(pontok=erdei_pontok, 10)
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

Könyvtárak

Általánosságban könyvtárakról

Az olyan programokat, amik magukban nem használhatóak, csak más programok megírásában segítenek, könyvtáraknak (library) hívjuk. (Ez más mint a fájlokat csoportosító mappa/könyvtár, bár a magyar szó ugyanaz.) A könyvtáraknak köszönhető hogy nem kell minden programozónak teljesen az alapoktól kezdenie a programokat, ezek nélkül nem lehetne olyan bonyolult programokat megírni amiket ma látunk. Az operációs rendszerek egyik feladata is gyakorlatilag az, hogy bizonyos feladatokat elvégezzen más programok számára, ezek a szolgáltatásai is egy könyvtárból érhetőek el. (Pl. hogy minden grafikus program az ablakot, keretét, gombjait hogy rajzolja ki.) Bármilyen programozási munkát végeztek bárhol, szinte biztos hogy szükségetek lesz külső könyvtárak használatára, úgyhogy most próbálkozunk barátkozni velük egy kicsit.

Mivel a könyvtárak célja hogy mások is használhassák őket, ezért egyik fontos komponensük a dokumentáció. A mai előadás jelentős részében, és a jövő heti gyakorlaton is fogunk a dokumentációval foglalkozni. A dokumentáció készülhet teljesen külön is, de a legtöbb programozási nyelvnél vannak többé kevésbé beépített eszközök az írására/kezelésére. A python-nál teljesen beépített megoldás van, erre kicsit később rátérünk.

Mivel az informatika nemzetközi nyelve angol, ezért ha valamilyen könyvtárat használni szeretnétek a munkátokhoz, a legvalószínűbb hogy angolul lesz hozzá a dokumentáció. Nincs szükség nyelvvizsgára, elég ha az informatikai néhány szakkifejezést értitek olvasva, de az angol ezen a területen elkerülhetetlen.

Speciális könyvtárak a nyelv beépített könyvtárai. Ezek olyan könyvtárak amik mindig mindenhol elérhetőek. A többi könyvtárat külön kell telepíteni ahhoz hogy használhatóak legyenek. A beépített könyvtárak általában alapvető feladatokat látnak el, amikre programozók széles körének szüksége lehet. De kicsit azért magasabb szintűek mint a beépített függvények. (Beépített függvények amik egyből használhatóak, mint pl. a már általatok is látott len() vagy range(). A beépített könyvtárakat most fogjuk nézni.)

Python könyvtár példa

Különböző programnyelveknél különböző mértékű a beépített könyvtár mérete. A python-nál, mivel egy modern, magas szintű nyelv, viszonylag nagy beépített könyvtár van. Azoknál a programnyelveknél szokott ennél jelentősen nagyobb lenni, amiket egy cég tart fenn, és egy hivatalos változat van, ezeknél a fenntartó cég által írt minden könyvtár beépítettnek számít. Ilyen pl. a C# vagy a Java.

A python könyvtára bőven elég ahhoz, hogy ebben a tárgyban nem fogunk kilépni belőle külső könyvtárakra. A teljes könyvtár dokumentációja a hivatalos lapon itt található meg. Tekintsük át ez alapján a tartalomjegyzék alapján hogy meddig terjed a hatóköre.

Demó pprint-el.

Több módja van az importálásnak. Alap módszer:

import pprint
s = pprint.pformat([1, 2, 3])

Gyakran használt dolgokat külön is kivehetjük:

from pprint import pformat
s = pformat([1, 2, 3])

Azt is lehet, hogy egy modulból mindent betöltünk egyszerre ilyen módon, de az nem ajánlott:

from pprint import *
s = pformat([1, 2, 3])

Ez azért nem ajánlott, mert ilyenkor a forráskódunkra ránézve nem látszik hogy melyik név honnan származik:

from math import *
from sajat_matek_konyvtar import *
 
a = sin(3.14) # Melyik import-bol van vajon?

Át is lehet nevezni az importált dolgot, ami jól jöhet ha hosszú a neve és nem akarjuk mindig leírni, vagy két azonos nevű dolgot is be akarunk importálni. Egyelőre nektek erre nincs szükségetek, de jó ha felismeritek ha látjátok:

from pprint import pformat as PF
s = PF([1, 2, 3])
 
import math
from sajat_konyvtar import math as sajat_math
a = math.sin(3.14) # Így egyértelmű


Saját könyvtár írása

Másik fájl betöltése

Vegyük a korábban írt kódot, és mentsük el egy atment.py nevű fájlba:

def atment(pontok, hatar = 40, sorban = True):
    nevek = []
    for nev in pontok:
        if pontok[nev] >= hatar:
            nevek.append(nev)
    if sorban:
        nevek.sort()
    return nevek
 
erdei_pontok = {
    "Roka" : 85,
    "Medve" : 20,
    "Nyuszi" : 95,
    "Farkas" : 45,
    "Suni" : 55}
 
print atment(erdei_pontok)
print atment(erdei_pontok, 10, False)
print atment(erdei_pontok, hatar=10, sorban=False)
print atment(erdei_pontok, sorban=False)
print atment(pontok=erdei_pontok)

Ez a fájl mindjárt egy meghívható modul is egyben. Ha ebben a könyvtárban futtatjuk a python-t, akkor az import atment paranccsal már be is lehet hívni. Ezután elérhető pl. az atment.atment() függvény. Próbáljuk ki!

Egy probléma amit mindjárt látunk, hogy amikor az import lefut, akkor kiír egy csomó mindent amit nem akarunk. Ez azért van, mert ilyenkor lefut az egész fájl, nem csak a függvénydefiníciók. Ezt úgy lehet elkerülni, ha azt a végső, teszelős részt betesszük egy

if __name__ == "__main__":

blokkba. Ez azt jelenti, hogy az a kód csak akkor futtatandó, ha a fájlt magában hívják meg, nem ha import-álják. Hogy ezt pontosan miért így kell megfogalmazni, az most nekünk mindegy.

Általában kétféle dolog szokott lenni ebben a blokkban:

  • teszteli az abban a fájlban megadott függvények helyes működését
  • vagy azt éri el parancssorbol lehessen a függvényt használni, és akkor a parancssorba írja ki a kimenetet

Egyelőre hagyjuk meg ezt az egyszerű tesztelést.

A modul nem csak függvényeket, hanem változókat, és egyéb (később tanult) dolgokat is tartalmazhat. Például a jelen esetben a sztenderd ponthatárt kitehetjük egy külön változóba, és akkor azt is el lehet érni a modul használói által is.

Dosctring

Korábban beszéltem arról, hogy mások által írt könyvtáraknál milyen jó a dokumentáció. Ebből következik, hogy általatok írt könyvtáraknál/moduloknál is milyen jó lenne!

A python-ban sztenderd módszer a modulok dokumentálására a docstring. Az első sornak egy mondatos összefoglalónak kell lennie, ponttal lezárva. (Van olyan alkalom amikor csak ez a sor jelenik meg.) A többi szabad formájú. Általában érdemes a paramétereket és a visszatérési értéket dokumentálni, ha lehet velük bármi meglepő.

A példafüggvény így néz ki ilyen egyszerű docstring-el (de akár az első sor is elég lehetne):

ponthatar = 40
 
def atment(pontok, hatar = ponthatar, sorban = True):
    """
    Visszaadja egy listaban hogy mely hallgatok mentek at egy ZHn.
 
    Parameterek:
        pontok: a hallgatok pontjai, szotarban, ami a nevhez pontot rendel.
        hatar: akkor ment at ha ennel nagyobb vagy egyenlo a pontja.
    """
    nevek = [nev for nev in pontok if pontok[nev] >= hatar]
    if sorban:
        nevek.sort()
    return nevek

Az így megírt docstring-et a python beépítve tudja használni, pl. a help paranccsal. Vagy, a python egyik beépített könyvtára HTML honlapot is tud belőle generálni. Valahogy így:

<python_helye>\Python27\Lib\pydoc.py -w atment

Linux-on elég annyi hogy

pydoc -w atment

Tesztelésről általában

Nagy project-eknél fontos, nektek igazából nem kell használni, de nem árt ha tudjátok mi az, hogy működik. Több ember együttműködésén segít.

Docstring teszt

A python beépített könyvtárai között van egy, ami a tesztelésre egy beépített megoldás, a doctest. Ez a docstring-el működik együtt. Az a lényege, hogy a dokumentációba teszünk példákat (amik amúgy is jó dokumentációk), és ezeket a példákat ő automatikusan le tudja ellenőrizni.

Végső kód:

ponthatar = 40
 
def atment(pontok, hatar = ponthatar, sorban = True):
    """
    Visszaadja egy listaban hogy mely hallgatok mentek at egy ZHn.
 
    Parameterek:
        pontok: a hallgatok pontjai, szotarban, ami a nevhez pontot rendel.
        hatar: akkor ment at ha ennel nagyobb vagy egyenlo a pontja.
 
    Pelda:
    >>> erdei_pontok = {
    ...     "Roka" : 85,
    ...     "Medve" : 20,
    ...     "Nyuszi" : 95,
    ...     "Farkas" : 45,
    ...     "Suni" : 55}
    >>> print atment(erdei_pontok)
    ['Farkas', 'Nyuszi', 'Roka', 'Suni']
    >>> print atment(erdei_pontok, 10, False)
    ['Medve', 'Farkas', 'Nyuszi', 'Suni', 'Roka']
    >>> print atment(erdei_pontok, hatar=20, sorban=False)
    ['Medve', 'Farkas', 'Nyuszi', 'Suni', 'Roka']
    >>> print atment(erdei_pontok, sorban=False)
    ['Farkas', 'Nyuszi', 'Suni', 'Roka']
    >>> print atment(pontok=erdei_pontok)
    ['Farkas', 'Nyuszi', 'Roka', 'Suni']
    """
    nevek = [nev for nev in pontok if pontok[nev] >= hatar]
    if sorban:
        nevek.sort()
    return nevek
 
if __name__ == "__main__":
    import doctest
    doctest.testmod()

Futtatva -v paraméterrel minden tesztet kiír, különben csak a hibásat.

Személyes eszközök