Seriál: V zajatí Pythona / 3. časť: Zložené príkazy a funkcie

August nám pri­nie­sol nie­len nez­ne­si­teľ­né tep­lo­ty, ale aj no­vú be­tu Pyt­ho­na 1.6, na kto­rú sa po­zrie­me, len čo vy­jde sta­bil­ná ver­zia. V tej­to čas­ti se­riá­lu si pre­be­rie­me naj­mä tie pr­vky ja­zy­ka, kto­rý­mi štruk­tú­ru­je­me prog­ra­my. Kon­krét­ne pô­jde o zlo­že­né prí­ka­zy, fun­kcie a bliž­šie sa po­zrie­me na do­ku­men­tač­né re­ťaz­ce.

Zlo­že­né prí­ka­zy

Zlo­že­né prí­ka­zy (com­pound sta­te­ments) slú­žia na vet­ve­nie prog­ra­mu. V Pyt­ho­ne je to po­dmie­ne­ný prí­kaz ifa cyk­ly whi­le a for, pri­čom je nie­len pri if (ako je to aj v iných prog­ra­mo­va­cích ja­zy­koch), ale aj pri cyk­loch for a whi­le je dos­tup­ná časť el­se:, kto­rá sa vy­ko­ná, ak ne­bu­de spl­ne­ná po­dmien­ka hlav­né­ho cyk­lu. Prv než sa po­zrie­me na kon­krét­ne prí­ka­zy, si však mu­sí­me vy­svet­liť, čo sú to blo­ky, kto­ré hod­no­ty v Pyt­ho­ne spĺňa­jú po­dmien­ky, a mu­sí­me sa po­zrieť na re­lač­né a lo­gic­ké ope­rá­to­ry.

Blo­ky

Blo­ky sú vlas­tne zos­ku­pe­nia prí­ka­zov (mô­že ísť aj o je­di­ný prí­kaz), kto­ré sa vy­uží­va­jú v zlo­že­ných prí­ka­zoch a ako te­lá fun­kcií. V blo­koch sa vy­tvá­ra­jú lo­kál­ne pre­men­né. Zna­me­ná to, že ak ste v zdro­jo­vom kó­de váš­ho prog­ra­mu pred blo­kom po­uži­li ur­či­tú pre­men­nú, tak tým, že ju uve­die­te v blo­ku, zos­ta­ne pô­vod­ný ob­sah tej­to pre­men­nej za­cho­va­ný! Jed­no­duc­ho po­ve­da­né, iden­ti­fi­ká­to­ry pre­men­ných v blo­ku sa mô­žu prek­rý­vať s tý­mi mi­mo blo­ku bez to­ho, aby sa zme­nil ob­sah rov­no­men­ných pre­men­ných mi­mo blo­ku. Blo­ky sú od­sa­de­né ur­či­tým kon­štan­tným po­čtom med­zier ale­bo ta­bu­lá­to­rov. V od­sa­de­ní jed­né­ho blo­ku nie je mož­né strie­dať med­zi med­ze­ra­mi a ta­bu­lá­tor­mi ani med­zi ich po­čtom. Ak sme te­da pr­vý ria­dok blo­ku od­sa­di­li dvo­ma med­ze­ra­mi, tak i dru­hý mu­sí byť od­sa­de­ný dvo­ma. Ďal­šie od­sa­de­nie vnút­ri blo­ku (napr. vno­re­nie ďal­šie­ho zlo­že­né­ho prí­ka­zu) mu­sí­me vy­ko­nať dvoj­ná­sob­nou hod­no­tou pred­chád­za­jú­ce­ho od­sa­de­nia, te­da v prík­la­de z pred­chád­za­jú­ce­ho riad­ka by to bo­li šty­ri med­ze­ry.

Po­dmien­ky

Prv než sa mô­že­me pus­tiť do sa­mot­ných zlo­že­ných prí­ka­zov, mu­sí­me ve­dieť, kto­ré hod­no­ty sa v Pyt­ho­ne po­va­žu­jú za prav­di­vé a kto­ré nie.

Nep­rav­di­vé hod­no­ty None (vy­svet­le­nie ďa­lej pri prí­ka­ze re­turn), čí­sel­né nu­ly, práz­dne sek­ven­čné dá­to­vé ty­py (re­ťaz­ce, po­lia, tup­le) a práz­dne slov­ní­ky
Prav­di­vé hod­no­ty Všet­ky os­tat­né hod­no­ty

Re­lač­né a lo­gic­ké ope­rá­to­ry

Na roz­diel od C všet­ky re­lač­né (po­rov­ná­va­cie) ope­rá­to­ry ma­jú tú is­tú prio­ri­tu, kto­rá je niž­šia ako pri arit­me­tic­kých ope­rá­to­roch. Čís­la sa po­rov­ná­va­jú arit­me­tic­ky, zna­ky po­dľa AS­CII hod­no­ty, pre­to napr. pla­tí, že "a" > "A". Re­ťaz­ce sa po­rov­ná­va­jú lexikog­ra­fic­ky, čo zna­me­ná, že pr­vý znak ľa­vé­ho re­ťaz­ca sa po­rov­ná s pr­vým zna­kom pra­vé­ho re­ťaz­ca, dru­hý s dru­hým, tre­tí s tre­tím atď. až do kon­ca jed­né­ho z re­ťaz­cov ale­bo do pr­vé­ho roz­die­lu med­zi tý­mi­to re­ťaz­ca­mi. Pre­to napr. pla­tí: "abcd" < "ab­cde", "abcd2" > "abcd1".

Tab. Re­lač­né ope­rá­to­ry
ope­rá­tor vý­znam
< men­šie ako
> väč­šie ako
== rov­ná sa
<= men­šie ako ale­bo sa rov­ná
>= väč­šie ako ale­bo sa rov­ná
!= ne­rov­ná sa
in je v sek­ven­čnom dá­to­vom ty­pe
not in nie je v sek­ven­čnom dá­to­vom ty­pe

Lo­gic­ké ope­rá­to­ry sa nám ho­dia v prí­pa­de, že po­tre­bu­je­me v jed­nom vý­ra­ze vy­jad­riť viac po­dmie­nok. Vý­ra­zom a > b and b < c ho­vo­rí­me Pyt­ho­nu, že obid­ve po­dmien­ky mu­sia byť spl­ne­né (mu­sí pla­tiť, že a je väč­šie ako b a sú­čas­ne že b je men­šie ako c). A a > b or b > c pre zme­nu udá­va, že sta­čí, aby pla­ti­la jed­na po­dmien­ka (a je väč­šie ako b ale­bo b je väč­šie ako c). Tre­tím a po­sled­ným lo­gic­kým ope­rá­to­rom je not, kto­rým ne­gu­je­me prav­di­vosť vý­ra­zu. Nap­rík­lad ak je v pre­men­nej a hod­no­ta 3 (prav­di­vá hod­no­ta), tak vý­raz not a je nep­rav­di­vá hod­no­ta. Lo­gic­ké ope­rá­to­ry ma­jú v Pyt­ho­ne úpl­ne naj­niž­šiu prio­ri­tu.

Tab. Lo­gic­ké ope­rá­to­ry
ope­rá­tor vý­znam
and lo­gic­ké or ("ale­bo")
not lo­gic­ké and ("a")
and ne­gu­je prav­di­vosť ope­ran­da

Prí­kaz if

Po­dmie­ne­ný prí­kaz if je dos­tup­ný sko­ro vo všet­kých prog­ra­mo­va­cích ja­zy­koch, Pyt­hon nie je vý­nim­ka. Prí­kaz if fun­gu­je tak­to: ak je spl­ne­ná po­dmien­ka1, vy­ko­ná sa blok1 a prí­kaz if sa skon­čí. Ďal­šie po­dmien­ky sa za­pi­su­jú po­mo­cou čas­ti elif:, a ak je jed­na z týc­hto po­dmie­nok spl­ne­ná, vy­ko­ná sa blok pri prís­luš­nej čas­ti elif: a prí­kaz if sa skon­čí. Čas­ti elif: nie sú po­vin­né a mô­že ich byť v kó­de prog­ra­mu viac. Po­mo­cou konštruk­cií s via­ce­rý­mi elif: sa nah­rad­zu­je prí­kaz switch z iných ja­zy­kov (napr. C). Blok v čas­ti el­se: sa vy­ko­ná, ak ani jed­na z pred­chád­za­jú­cich po­dmie­nok ne­bo­la spl­ne­ná, tá­to časť ta­kis­to nie je po­vin­ná. Prí­kaz if sa za­pi­su­je tak­to:

if po­dmien­ka1:
   blok1
elif po­dmien­ka2:
   blok2
elif ... blok ...
el­se:
   blok

Prík­lad:

 cis­lo=-2
 if cis­lo < 0:
...     print 'cis­lo je za­por­ne'
... elif cis­lo  0:
...     print 'cis­lo je klad­ne'
... el­se:
...     print 'cis­lo je 0'
... 
cis­lo je za­por­ne

Cyk­lus whi­le

Cyk­lus whi­le má za úlo­hou opa­ko­vať blok, po­kým má po­dmien­ka prav­di­vú hod­no­tu. Časť el­se: nie je po­vin­ná a blok sto­ja­ci pri tej­to čas­ti sa vy­ko­ná, ak po­dmien­ka nie je spl­ne­ná. Zá­pis:

whi­le po­dmien­ka:
   blok
el­se:
   blok

Prík­lad:

 a, b = 0, 1
 whi­le b < 100:
...     print b,
...     a, b = b, a+b
... 
1 1 2 3 5 8 13 21 34 55 89

Cyk­lus for

V Pyt­ho­ne sa cyk­lus for troš­ku od­li­šu­je od im­ple­men­tá­cie v C ale­bo Pas­ca­le. Hlav­nou úlo­hou pyt­ho­nov­ské­ho prí­ka­zu for je prec­hád­zať med­zi pr­vka­mi sek­ven­čné­ho dá­to­vé­ho ty­pu (re­ťa­zec, po­le, tup­le). Časť el­se: je ne­po­vin­ná a vy­ko­ná sa vte­dy, ak zly­ha­lo vy­ko­na­nie hlav­nej čas­ti cyk­lu for (napr. keď je sek­ven­čný_dá­to­vý_typ prázd­ny). Cyk­lus for sa za­pi­su­je tak­to:

for pre­men­ná in sek­ven­čný_dá­to­vý_typ:
    blok
el­se:
   blok

Prík­lad:

 a='Pyt­hon', 'Perl', 'C++', 'Ja­va'
 for i in ran­ge(len(a)):
...     print i, a[i]
... 
0 Pyt­hon
1 Perl
2 C++
3 Ja­va

Prí­ka­zy sko­ku

V cyk­loch for a whi­le sú do­vo­le­né nas­le­du­jú­ce prí­ka­zy sko­ku, pre mno­hých z nás zná­me aj z iných prog­ra­mo­va­cích ja­zy­kov:

break

Prí­kaz break ukon­čí naj­bliž­ší prí­kaz for ale­bo whi­le. Ak ukon­če­ný prí­kaz ob­sa­hu­je časť el­se:, tá bu­de ig­no­ro­va­ná. Troš­ku nez­my­sel­ný (ďal­ší prík­lad náj­de­te vo fun­kcii pr­vo­cis­lo2() v od­se­ku „prí­kaz re­turn“), ale funkč­ný prík­lad, kto­rý veľ­mi pek­ne uka­zu­je čin­nosť break:

 for a in ran­ge(1,11):
...     if a  3:
...             break
...     print a
... 
1
2
3

con­ti­nue

Prí­kaz con­ti­nue okam­ži­te ukon­čí prá­ve vy­ko­ná­va­nú sluč­ku a po­kra­ču­je ďal­šou sluč­kou (ak je stá­le spl­ne­ná po­dmien­ka – cyk­lus whi­le – ale­bo ak sa eš­te nep­reš­li všet­ky pr­vky v sek­ven­čnom dá­to­vom ty­pe – cyk­lus for) v naj­bliž­šom cyk­le for ale­bo whi­le.

 for a in ran­ge(1,11):
...     if a%2 == 0:
...             con­ti­nue
...     print a
... 
1
3
5
7
9

Prí­kaz pass

Prí­kaz pass ne­ro­bí nič. Po­uží­va sa ako prázd­ny blok, keď je syn­tak­tic­ky ne­vyh­nut­né uviesť blok a my v na­šom prog­ra­me ne­pot­re­bu­je­me ni­ja­ký prí­kaz. Prík­lad:

whi­le 1: 
... pass #ca­ka­me na pre­ru­se­nie z kla­ves­ni­ce

Fun­kcie

Po­mo­cou fun­kcií „roz­kla­dá­me“ veľ­ké, ťaž­ko rie­ši­teľ­né prob­lé­my na men­šie čas­ti, kto­rých rie­še­nie je hrač­kou. To­to je pr­vá vý­ho­da po­uži­tia fun­kcií. Dru­há spo­čí­va v tom, že časť kó­du prog­ra­mu, kto­rú vy­uží­va­me viac­krát, pí­še­me len raz.

De­fi­no­va­nie fun­kcií

Fun­kcie sa de­fi­nu­jú kľú­čo­vým slo­vom def, za kto­rým mu­sí nas­le­do­vať iden­ti­fi­ká­tor s me­nom fun­kcie. Za me­nom mu­sia byť v kla­sic­kých zá­tvor­kách uve­de­né ar­gu­men­ty (ak fun­kcia ne­má ar­gu­men­ty, uve­die­me práz­dne zá­tvor­ky) a za ar­gu­men­tmi nas­le­du­je dvoj­bod­ka. Pr­vý ria­dok by mal byť do­ku­men­tač­ný re­ťa­zec. V ďal­šom riad­ku nas­le­du­je blok s te­lom fun­kcie. Prík­lad:

 def pr­vo­cis­lo(n):
...        for x in ran­ge(2,n):
...                if n % x == 0:
...                        print n, '=', x, '*', n/x
...                        break
...        el­se:
...                print n, 'je pr­vo­cis­lo'
...
 pr­vo­cis­lo(8)
8 = 2 * 4
 pr­vo­cis­lo(7)
7 je pr­vo­cis­lo

Uve­de­ním me­na fun­kcie bez zá­tvo­riek s ar­gu­men­tmi zís­ka­me ad­re­su fun­kcie. Tú­to hod­no­tu je mož­né pri­ra­diť k no­vé­mu iden­ti­fi­ká­to­ru. Zís­ka­me tak mož­nosť vo­lať tú is­tú fun­kciu dvo­ma me­na­mi.

pr­vo­cis­lo #ad­re­sa fun­kcie

dru­he_me­no=pr­vo­cis­lo
dru­he_me­no(16)
16 = 2 * 8 

Štan­dar­dné hod­no­ty ar­gu­men­tov

Ar­gu­men­tom fun­kcií je mož­né pri­ra­diť štan­dar­dné hod­no­ty. Ak po­tom vo­lá­me fun­kciu s me­nej ar­gu­men­tmi, ako bo­lo de­fi­no­va­né, po­uži­jú sa hod­no­ty ar­gu­men­tov uve­de­né v de­fi­ní­cii fun­kcie. Prík­lad:

def po­zdrav(s='ahoj!'):
... print s
... 
po­zdrav()
ahoj!
po­zdrav('dob­ry den!')
dob­ry den!

Ak po­zná­me v de­fi­ní­cii fun­kcie me­ná ar­gu­men­tov so štan­dar­dnou hod­no­tou, je mož­né pri vo­la­ní fun­kcie uviesť tie­to ar­gu­men­ty s no­vou hod­no­tou. Naj­lep­šie sa to uká­že na prík­la­de:

def po­zdrav2(ko­ho, ako='Dob­ry den, '):
... print ako + ko­ho + '!'
... 
po­zdrav2('Pe­ter') #kla­sic­ke vo­la­nie fun­kcie
Dob­ry den, Pe­ter!
po­zdrav2('Mar­tin', ako='Ahoj, ') #ar­gu­ment "ako" dos­ta­ne no­vu hod­no­tu
Ahoj, Mar­tin!

Pri de­fi­no­va­ní fun­kcie je ne­vyh­nut­né uviesť ar­gu­men­ty bez štan­dar­dnej hod­no­ty pred ar­gu­men­tmi so štan­dar­dnou hod­no­tou.

Prí­kaz re­turn

Pro­ce­dú­ry sú v Pyt­ho­ne kon­ci­po­va­né po­dob­ne ako v C. Sú to vlas­tne fun­kcie, kto­ré nev­ra­ca­jú ni­ja­kú hod­no­tu. Aby fun­kcia vra­ca­la hod­no­tu, exis­tu­je prí­kaz re­turn. Ten­to prí­kaz okam­ži­te ukon­čí fun­kciu a spô­so­bí, že fun­kcia vrá­ti hod­no­tu, kto­rú dos­ta­ne prí­kaz re­turn ako ar­gu­ment. Vrá­tiť sa da­jú ce­lé ob­jek­ty, ako napr. po­le v tom­to prík­la­de up­ra­ve­nej fun­kcie pr­vo­cis­lo():

 def pr­vo­cis­lo2(n):
...         "vra­ti po­le s pr­vo­cis­la­mi do n"
...         vy­sle­dok=[]
...         for n in ran­ge(2, n):
...                 for x in ran­ge(2,n):
...                         if n% x == 0:
...                                 break
...                 el­se:
...                         vy­sle­dok.ap­pend(n)
...         re­turn vy­sle­dok
...
 a=pr­vo­cis­lo2(30)
 a
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

Pred chví­ľou ste čí­ta­li, že pro­ce­dú­ry nev­ra­ca­jú ni­ja­kú hod­no­tu, čo však nie je cel­kom prav­da. Ak nie je fun­kcia ukon­če­ná prí­ka­zom re­turn ale­bo ak re­turn nev­ra­cia nič (ni­ja­ký ob­jekt), fun­kcia vra­cia im­pli­cit­ne hod­no­tu None, kto­rá slú­ži ako nep­rav­di­vá hod­no­ta.

Fun­kcie s pre­men­ným po­čtom ar­gu­men­tov

Ak chce­me v Pyt­ho­ne vy­tvo­riť fun­kciu s pre­men­ným po­čtom ar­gu­men­tov, v de­fi­ní­cii fun­kcie uve­die­me pred ar­gu­men­tom znak hviez­dič­ky. Hod­no­ty ar­gu­men­tu s hviez­dič­kou sú ulo­že­né v tup­le. Prík­lad:

 def fun_s_prem_poc­tom_arg(*arg):
...     print 'tup­le s hod­no­ta­mi *arg: ', arg
...     print 'jed­not­li­ve hod­no­ty:'
...     for a in ran­ge(len(arg)):
...             print a, arg[a]
... 
 fun_s_prem_poc­tom_arg("arg1",23,'Pyt­hon')
tup­le s hod­no­ta­mi *arg:  ('arg1', 23, 'Pyt­hon')
jed­not­li­ve hod­no­ty:
0 arg1
1 23
2 Pyt­hon

V prí­pa­de, že uve­die­me na­mies­to jed­nej hviez­dič­ky dve, bu­de od nás Pyt­hon oča­ká­vať ar­gu­men­ty s pri­ra­de­ný­mi hod­no­ta­mi po­mo­cou zna­ku "=". Pri vo­la­ní fun­kcie sa hod­no­ty tak­to de­fi­no­va­né­ho ar­gu­men­tu od­ov­zda­jú ako slov­ník, kto­ré­ho kľú­če bu­dú ar­gu­men­ty a hod­no­ty kľú­čov bu­dú hod­no­ty ar­gu­men­tov. Naj­lep­šie to po­cho­pí­te na prík­la­de:

 def vy­pis_uda­je(**uda­je):
...     for kluc in uda­je.keys():
...             print kluc, ': ', uda­je[kluc]
... 
 vy­pis_uda­je(Me­no='Jan­ko Hras­ko', Po­vo­la­nie='stu­dent')
Me­no :  Jan­ko Hras­ko
Po­vo­la­nie :  stu­dent

Je mož­né ľu­bo­voľ­ne kom­bi­no­vať kla­sic­ké ar­gu­men­ty s „hviez­dič­ko­vý­mi“ ar­gu­men­tmi. V de­fi­ní­cii fun­kcie však tre­ba uviesť naj­prv kla­sic­ké ar­gu­men­ty, za ni­mi ar­gu­ment s jed­nou hviez­dič­kou a po­tom ar­gu­ment s dvo­ma hviez­dič­ka­mi. Prík­lad je spo­je­ný s prík­la­dom na do­ku­men­tač­ný re­ťa­zec v ďal­šom od­se­ku.

Do­ku­men­tač­né re­ťaz­ce

S do­ku­men­tač­ným re­ťaz­com sme sa už stret­li pri prog­ra­me lin­cal a pred chví­ľou vo fun­kcii pr­vo­cis­lo2(). Ako sme si už po­ve­da­li v pre­doš­lej čas­ti se­riá­lu, do­ku­men­tač­né re­ťaz­ce slú­žia na do­ku­men­to­va­nie ľu­bo­voľ­ných ob­jek­tov v Pyt­ho­ne, te­da aj fun­kcií, kto­ré sú v Pyt­ho­ne tiež rep­re­zen­to­va­né ako ob­jek­ty. Do­ku­men­tač­ný re­ťa­zec by mal byť v ďal­šom riad­ku hneď po de­fi­ní­cii fun­kcie a mal by byť kon­ci­po­va­ný struč­ne. Ak je v do­ku­men­ta­čom re­ťaz­ci viac riad­kov, dru­hý ria­dok by mal byť prázd­ny, aby od­de­ľo­val pr­vý ria­dok (maximál­ne struč­né zhr­nu­tie) od os­tat­né­ho textu. Uvád­za­nie do­ku­men­tač­ných re­ťaz­cov pri kaž­dom ob­jek­te je ne­pí­sa­ným pra­vid­lom všet­kých prog­ra­má­to­rov v Pyt­ho­ne a bo­lo by veľ­mi dob­ré spra­viť si z toh­to pra­vid­la zvyk. K do­ku­men­tač­né­mu re­ťaz­cu pris­tu­pu­je­me po­mo­cou konštruk­cie ob­jekt.__doc__. Do­ku­men­tač­né re­ťaz­ce sa zvyk­nú ozna­čo­vať aj ako docstrings. Ob­li­gát­ny prík­lad:

 def in­ven­tar(in­sti­tu­cia,*ad­re­sa,**ob­jek­ty):
...     """Vy­pi­se in­ven­tar in­sti­tu­cie z ad­re­sy s ob­jek­tmi a ich po­ctom.
...                                            
... Ob­jek­ty sa za­da­va­ju v sty­le: me­no_ob­jek­tu=po­cet."""
...     print in­sti­tu­cia
...     print '-'*len(in­sti­tu­cia)
...     for a in ad­re­sa:
...             print a
...     print #prazd­ny ria­dok
...     for a in ob­jek­ty.keys():
...             print ob­jek­ty[a], a
... 
 in­ven­tar('Fir­ma A', 'Hras­ko­va 23', '85101 Bra­tis­la­va', stol=1, sto­lic­ky=4)
Fir­ma A
-------
Hras­ko­va 23
85101 Bra­tis­la­va

4 sto­lic­ky
1 stol
 print in­ven­tar.__doc__ 
Vy­pi­se in­ven­tar in­sti­tu­cie z ad­re­sy s ob­jek­tmi a ich po­ctom.

Ob­jek­ty sa za­da­va­ju v sty­le: me­no_ob­jek­tu=po­cet.

Na­bu­dú­ce

De­tail­ne si pre­be­rie­me jed­nu z naj­dô­le­ži­tej­ších ve­cí v Pyt­ho­ne – mo­du­ly.

Ďal­šie čas­ti >>

Zdroj: PC Revue



Ohodnoťte článok:
   
 
 
  Zdieľaj cez Facebook Zdieľaj cez Google+ Zdieľaj cez Twitter Zdieľaj cez LinkedIn Správy z RSS Správy na smartfóne Správy cez newsletter