summaryrefslogtreecommitdiff
path: root/python/problems/functions
diff options
context:
space:
mode:
Diffstat (limited to 'python/problems/functions')
-rw-r--r--python/problems/functions/functions_sl.html587
-rw-r--r--python/problems/functions/sl.py2
2 files changed, 588 insertions, 1 deletions
diff --git a/python/problems/functions/functions_sl.html b/python/problems/functions/functions_sl.html
new file mode 100644
index 0000000..1bd0a25
--- /dev/null
+++ b/python/problems/functions/functions_sl.html
@@ -0,0 +1,587 @@
+<!DOCTYPE html>
+<html lang="sl">
+<head>
+ <meta charset="utf-8" />
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="/css/codeq.css" />
+ <link rel="stylesheet" type="text/css" href="../../style.css" />
+</head>
+<body>
+
+<h1> Kako definiramo funkcije? </h1>
+
+<p>Funkcije smo si doslej predstavljali kot škatlice: nekaj gre noter
+(temu smo in bomo rekli <em>argument</em>), nekaj pride ven (temu se reče
+ rezultat funkcije), vmes pa se lahko še kaj opaznega dogaja, recimo
+ izpisuje. Primer funkcije, ki je počela vse to, je <code>input</code>: kot
+argument smo ji povedali, kaj naj vpraša uporabnika; kot rezultat je vrnila,
+kar je vtipkal uporabnik; vmes se je zgodilo to, da je funkcija nekaj vprašala
+uporabnika in počakala, da je le-ta odgovoril. Druga funkcija, ki smo jo
+srečali, je bila <code>sqrt</code>, ki dobi kot argument neko število in vrne
+njegov koren. Vmes se ne dogaja nič opaznega, funkcija le "neopazno" naredi,
+kar mora narediti.</p>
+
+<p>S tem, kako delujejo funkcije in kako kaj naredijo, se doslej nismo
+ukvarjali. Te stvari so za nas napisali drugi (hvala, hvala) in mi jih lahko
+uporabljamo, ne da bi nas vznemirjalo vprašanje, kako so napisane. S tem, kako
+so napisane funkcije, ki so jih naredili drugi, se tudi v prihodnje ne bomo
+ukvarjali. Pač pa se bomo danes naučili pisati svoje.</p>
+
+
+<h2>Popolna števila</h2>
+
+<p>Število je <em>popolno</em>, če je enako vsoti svojih deliteljev. 28 je
+deljivo z 1, 2, 4, 7 in 14 ter je popolno, saj je 1+2+4+7+14 ravno 28. Napišimo
+program, ki sestavi seznam vseh popolnih števil do 1000.</p>
+
+<h3>Delitelji števila</h3>
+
+<p>Znamo napisati program, ki sestavi seznam vseh deliteljev nekega števila
+ <em>n</em>?</p>
+
+<pre>
+n = int(input("Vnesi število: "))
+
+s = []
+for i in range(1, n):
+ if n % i == 0:
+ s.append(i)
+
+print(s)</pre>
+
+<p>Najprej naredimo prazen seznam, nato gremo prek vseh števil od 1 do n in
+če število deli <code>n</code>, ga dodamo v <code>s</code>.</p>
+
+<p>Kaj ne bi bilo lepo, če bi imel Python kar funkcijo <code>delitelji</code>,
+ki bi jo lahko uporabili? Potem bi lahko napisali kar</p>
+
+<pre>
+stevilka = int(input("Vnesi število: "))
+s = delitelji(stevilka)
+print(s)</pre>
+
+<p>Napišimo si takšno funkcijo, da jo bomo lahko klicali.</p>
+
+<pre>def delitelji(n):
+ s = []
+ for i in range(1, n):
+ if n % i == 0:
+ s.append(i)
+ return s</pre>
+
+<p>Definicijo funkcije začnemo z <code>def</code>; to je rezervirana beseda, ki
+pomeni, da to, kar sledi, ni "program, ki ga je treba takoj izvesti", temveč
+funkcija. Z drugimi besedami, <code>def delitelji</code> pomeni: "<em>kadar bo
+kdo poklical funkcijo <code>delitelji</code>, naredi naslednje:</em>".</p>
+
+<p>Imenu sledijo oklepaji, v katerih navedemo <em>imena argumentov
+funkcije</em>. V našem primeru bo funkcija zahtevala en argument. Torej, ta,
+ki bo poklical funkcijo, bo moral v oklepaje napisati eno reč (upamo, da bo
+napisal število, sicer pa naj si sam pripiše posledice).</p>
+
+<p>Tista reč, ki jo bomo ob klicu funkcije podali kot argument, se bo znotraj
+funkcije pojavila kot spremenljivka z imenom <code>n</code>. Takšno ime smo
+namreč uporabili v prvi vrstici, v "glavi" funkcije. Vrednosti ji ne bomo
+priredili: ko bo nekdo poklical funkcijo, bo Python tej "spremenljivki" kar sam
+od sebe priredil vrednost, ki jo bo "klicatelj" napisal kot argument funkcije.
+Če torej nekdo pokliče
+
+<pre>s = delitelji(35)</pre>
+
+bo imel <code>n</code> vrednost 35 in če pokliče
+
+<pre>s = delitelji(13)</pre>
+
+bo imel <code>n</code> vrednost 13. <code>n</code> ima vrednost argumenta.</p>
+
+<p>Za <code>def delitelji(n)</code> sledi dvopičje in zamik. Vse, kar sledi
+takole zamaknjeno, je koda funkcije. Kaj mora narediti le-ta? No, tisto, kar
+pač dela funkcija: sestaviti seznam deliteljev <code>n</code>. To pa ne le
+znamo narediti, temveč smo celo ravno prejle tudi zares naredili in lahko le
+skopiramo.</p>
+
+<p>Na koncu (ali tudi že kje vmes - bomo že videli primer) funkcija pove, kaj
+naj klicatelj dobi kot rezultat. To stori s stavkom <code>return s</code>.</p>
+
+<h3>Geometrija</h3>
+
+<p>Napišimo funkcijo, ki dobi kot argument dolžine stranic trikotnika in vrne
+ njegovo ploščino. Ta funkcija bo imela tri argumente; poimenujmo jih
+ <code>a</code>, <code>b</code> in <code>c</code>.
+
+
+<pre>from math import *
+def ploscina_trikotnika(a, b, c):
+ s = (a + b + c) / 2
+ return sqrt(s * (s - a) * (s - b) * (s - c))</pre>
+
+<p>Ko smo pri tem, napišimo še funkcijo funkcijo za obseg trikotnika ter za
+ obseg in ploščino kroga.</p>
+
+<pre>from math import *
+
+def obseg_trikotnika(a, b, c):
+ return a + b + c
+
+def ploscina_kroga(r):
+ return pi * r ** 2
+
+def obseg_kroga(r):
+ return 2 * pi * r</pre>
+
+<h3>Vsota števil v seznamu</h3>
+
+<p>Zdaj napišimo drugo funkcijo: funkcijo, ki dobi seznam števil in izračuna
+njihovo vsoto.</p>
+
+<pre>def vsota(s):
+ vsota = 0
+ for e in s:
+ vsota += e
+ return vsota</pre>
+
+<p>Funkcija ima spet en argument, tokrat smo ga poimenovali <code>s</code>.
+Ta argument bo seznam števil, ki jih je potrebno sešteti. Funkcija gre - z
+zanko <code>for</code> - prek tega seznama in sešteva, kot smo počeli že
+prejšnji teden, le brez funkcij. Na koncu rezultata ne izpiše
+(<code>print</code>), kot smo delali doslej, temveč ga vrne
+(<code>return</code>).</p>
+
+<p>(Mimogrede povejmo še, da nam funkcije <code>vsota</code> ne bi bilo
+potrebno napisati, saj obstaja: imenuje se <code>sum</code>.)</p>
+
+
+<h4>Za napredno misleče</h4>
+
+<p>Nekateri se sprašujejo, kako funkcija ve, kakšnega tipa bodo argumenti,
+ki jih bo dobila. Nekateri se zdaj, ko so izvedeli, da se nekateri sprašujejo
+o tem, sprašujejo, zakaj bi se kdo to spraševal.</p>
+
+<p>Vsebina tega razdelka je namenjena samo prvim. Kasneje bo vse, kar pišemo
+tu, postalo samoumevno, ne da bi bilo potrebno razlagati. Tule pa povejmo
+zaradi tistih, ki prihajajo iz drugih jezikov.</p>
+
+<p>V nekaterih jezikih je potrebno za vsako spremenljivko, preden jo uporabimo,
+povedati, kakšnega tipa bo. Python ni eden izmed teh "nekaterih jezikov".
+Podobno je z argumenti funkcij. V nekaterih jezikih bi morali povedati,
+kakšnega tipa bodo argumenti funkcije in kakšen bo rezultat. Tudi takšen
+Python ni. Funkcija sprejme, kar sprejme in vrača, kar vrača.</p>
+
+<p>Za primer vzemimo preprostejšo funkcijo <code>vsota</code>, ki ji podamo dva
+ argumenta, funkcija pa vrne njuno vsoto.</p>
+
+<pre>def vsota(a, b):
+ return a + b</pre>
+
+<p>Če jo pokličemo z <code>vsota(2, 5)</code>, vrne <code>2 + 5</code>, torej
+ <code>7</code>. Če jo pokličemo z <code>vsota("Ana", "Marija")</code> vrne
+ <code>"Ana" + "Marija"</code>, torej <code>"AnaMarija"</code>. Če jo
+ pokličemo z <code>vsota(2, "Ana")</code>, poskuša izračunati
+ <code>2 + "Ana"</code> in vrne napako, ker se ne da seštevati števil in
+ nizov.</p>
+
+<p>Jezikom, ki delajo tako, pravimo dinamično tipizirani jeziki. Stvar deluje
+(približno) tako, da Python, ko pride do <code>a + b</code>, reče objektoma
+<code>a</code> in <code>b</code>, naj se seštejeta. Če se znata, je to v redu,
+če ne, pa javita napako in Python jo izpiše. Python v resnici ne zna seštevati,
+seštevati (se) znajo objekti.</p>
+
+<p>Vrnimo se k prvi funkciji <code>vsota</code>, oni od prej. Kaj bi se
+ zgodilo, če bi dali funkciji namesto seznama kaj drugega, recimo
+ terko ali kaj podobnega? No, preskusimo jo nekoliko.</p>
+
+<pre> vsota([1, 5, 3])
+9
+>>> vsota((1, 5, 3))
+9
+>>> vsota(range(4))
+6</pre>
+
+<p>S seznamom dela. Prvi klic pomeni isto, kot če bi napisali:
+<pre>s = [1, 5, 3]
+v = 0
+for e in s:
+ v += e</pre>
+
+Drugi klic je podoben, le da je <code>s</code> zdaj terka <code>(1, 5, 3)</code>,
+torej dobimo
+
+<pre>v = 0
+for e in (1, 5, 3):
+ v += e</pre>
+
+Tretji klic pa je isto, kot če bi rekli
+
+<pre>v = 0
+for e in range(4):
+ v += e</pre>
+</p>
+
+<p>Kaj pa, če bi namesto seznama celih števil podali seznam necelih?</p>
+
+<pre>>>> vsota([1.3, 2.2, 3.1])
+6.6</pre>
+
+<p>Dela, jasno. Zakaj pa ne bi?</p>
+
+<p>Kaj pa, če bi dali seznam nizov? Poglejmo, poučno bo.</p>
+
+<pre>>>> vsota(["Ana", "Berta", "Cilka"])
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "<stdin>", line 4, in vsota
+TypeError: unsupported operand type(s) for +=: 'int' and 'str'</pre>
+
+<p>Zgodi se tole. Najprej je <code>v</code> enak 0. V prvem koraku zanke
+poskuša izračunati <code>0 + "Ana"</code>, kar se ne da.</p>
+
+<p>Funkcijo je mogoče popraviti, da bo delovala tudi za nize. </p>
+
+<pre>def vsota(s):
+ v = None
+ for e in s:
+ if v == None:
+ v = e
+ else:
+ v += e
+ return v</pre>
+
+<p>(<br/>Komur se mozga, naj razmisli, zakaj dela tudi naslednja (grda)
+ različica funkcije:</p>
+<pre>def vsota(s):
+ v = None
+ for e in s:
+ v = v and v + e or e
+ return v</pre>
+<p>.)</p>
+
+<p>Tule smo torej naleteli na <code>None</code>. Tole je kar tipična situacija,
+ v kateri ga uporabimo. <code>v</code>-ju moramo bo v začetku dati neko
+ vrednost, ki bo povedala, da še nima nobene vrednosti. <code>None</code> je
+ idealna konstanta, s katero povemo kaj takega. V zanki preverimo, ali je
+ <code>v</code> še vedno nič in mu v tem primeru priredimo <code>e</code>,
+ sicer mu prištejemo <code>e</code>.</p>
+
+<p>Razlika je v tem, da <code>v</code>-ju zdaj ne priredimo vrednosti že pred
+zanko, temveč jo dobi šele pri prvem elementu zanke. Tako bo gotovo pravega
+tipa. Zdaj zna seštevati vse živo.</p>
+
+<pre>>>> vsota([1, 2, 3])
+6
+>>> vsota(["Ana", "Benjamin", "Cilka"])
+'AnaBenjaminCilka'</pre>
+
+<p>Kaj pa tole?</p>
+
+<pre>>>> vsota("Benjamin")
+'Benjamin'</pre>
+
+<p>Zanka <code>for</code> gre prek niza in sešteje njegove črke. Rezultat je,
+seveda, spet isti niz.</p>
+
+<p>Pač pa funkcija ne deluje, če ji damo seznam, ki vsebuje reči, ki jih ni
+mogoče sešteti.</p>
+
+<pre>>>> vsota([1, "a"])
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "<stdin>", line 8, in vsota
+TypeError: unsupported operand type(s) for +=: 'int' and 'str'</pre>
+
+
+
+<h3>Popolno število</h3>
+
+<p>Vrnimo se k popolnim številom. Rekli smo, da je število popolno, če je enako
+ vsoti svojih deliteljev. Lahko bi torej rekli</p>
+
+<pre>stevilo = int(input("Vnesi število: "))
+d = delitelji(stevilo)
+v = vsota(d)
+if v == d:
+ print("Število", stevilo, "je popolno")
+else:
+ print("Število", stevilo, "ni popolno")</pre>
+
+<p>vendar ne bomo. Napisali bomo funkcijo, ki vrne <code>True</code>, če je
+število popolno in <code>False</code>, če ni.</p>
+
+<pre>def popolno(n):
+ d = delitelji(n)
+ v = vsota(d)
+ return v == n</pre>
+
+<p>Pazite, tule nismo pisali</p>
+
+<pre>def popolno(n):
+ d = delitelji(n)
+ v = vsota(d)
+ if v == n:
+ return True
+ else:
+ return False</pre>
+
+<p>Lahko bi, vendar bi bilo smešno. Pač pa lahko funkcijo še skrajšamo (in
+navadno bi jo tudi res), takole</p>
+
+<pre>def popolno(n):
+ return vsota(delitelji(n)) == n</pre>
+
+<p>Končno ostane še program, ki bo z uporabo gornje funkcije sestavil seznam
+vseh popolnih števil manjših od 1000.
+V njem z zanko <code>for</code> preštejemo do 1000, za vsako število posebej
+preverimo, ali je popolno in če je, ga dodamo na seznam.</p>
+
+<pre>s = []
+for i in range(1, 1001):
+ if popolno(i):
+ s.append(i)
+
+print(s)</pre>
+
+<p>Lepo prosim, ne pišite <code>if popolno(i) == True:</code>. Smo že povedali,
+zakaj, ne?</p>
+
+<h2>Klici funkcij</h2>
+
+<p>Najprej zberimo vse skupaj:</p>
+
+<pre>def delitelji(n):
+ s = []
+ for i in range(1, n):
+ if n % i == 0:
+ s.append(i)
+ return s
+
+def vsota(s):
+ v = 0
+ for e in s:
+ v += e
+ return v
+
+def popolno(n):
+ d = delitelji(n)
+ v = vsota(d)
+ return v == n
+
+
+s = []
+for i in range(1, 1001):
+ if popolno(i):
+ s.append(i)
+
+print(s)</pre>
+
+<p>Kako se izvaja tako napisan program? Malo drugače, kot smo vajeni. Začetek
+programa - vse do mesta <code>s = []</code>, so definicije funkcij. Python tega
+dela programa ne izvede, le zapomni si funkcije, da jih bo kasneje lahko
+poklical. Stvari se začnejo zares dogajati šele, pri <code>s = []</code>. Ko
+program pride do klica funkcije <code>popolno</code>, skoči v to funkcijo --
+vendar si zapomni, odkod je skočil, tako da se bo kasneje lahko vrnil na to
+mesto.</p>
+
+<p>Prav. Zdaj smo v funkciji <code>popolno</code> in <code>n</code> je neka
+številka (najprej 1, naslednjič bo 2 in tako naprej). Že takoj, v prvi
+vrstici skoči izvajanje v funkcijo <code>delitelji</code>. Ta sestavi seznam
+deliteljev in ga vrne - tistemu, ki jo je poklical, funkciji
+<code>popolno</code>. Nato se nadaljuje izvajanje funkcije <code>popolno</code>:
+ta v naslednji vrsti pokliče funkcijo <code>vsota</code>. Funkcija
+<code>vsota</code> izračuna in vrne vsoto. Spet smo v funkciji
+<code>popolno</code>, ki izračuna vrednost izraza <code>v == n</code>;
+vrednost izraza je <code>True</code> ali <code>False</code>. Funkcija
+<code>popolno</code> ga vrne tistemu, ki jo je klical, se pravi oni zanki
+na koncu skripte. Če je rezultat <code>True</code>, dodamo število v seznam,
+sicer ne.</p>
+
+<p>Ta program je lep zato, ker je pregleden. Razdelili smo ga na tri funkcije,
+vsaka opravlja svoje delo. Ko pišemo eno funkcijo, se ne ukvarjamo
+s celo sliko, temveč le s tem, kar počne ta funkcija. Če mislimo
+le na eno stvar naenkrat, nam bo lažje programirati in manj se bomo motili.</p>
+
+<h2>Rezultat sredi funkcije</h2>
+
+<p>Napišimo funkcijo, ki pove, ali je dano število praštevilo. Vrnila bo
+<code>True</code> (je) ali <code>False</code> (ni).</p>
+
+<p>Prejšnjič smo v te namene spoznali <code>break</code> - <code>break</code>
+ je bil ukaz, s katerim smo lahko prekinili zanko. No, prekinemo jo lahko
+ tudi z <code>return</code>.</p>
+
+<pre>def prastevilo(n):
+ for i in range(2, n):
+ if n % i == 0:
+ return False
+ return True
+</pre></p>
+
+<p>Prvi <code>return</code> je znotraj stavka <code>if</code>. Če odkrijemo,
+da kakšno število med 2 in n-1 deli n (se pravi, če je ostanek po deljenju
+<code>n</code> z <code>i</code> enak 0), dano število ni praštevilo in vrnemo
+<code>False</code>. S tem se izvajanje funkcije prekine, funkcija vrne
+rezultat in konec. Nobenega <code>break</code> ali česa podobnega ne
+potrebujemo. <code>return</code> vedno konča izvajanje funkcije. Do drugega
+<code>return</code>a tako pridemo le, če se ni izvedel prvi
+<code>return</code>. To pa seveda pomeni, da ni bilo nobenega števila, ki bi
+delilo dano število <code>n</code>.</p>
+
+
+<h2>Funkcije (navadno) vračajo rezultate, ne izpisujejo</h2>
+
+<p>Iz neznanega razloga so študentom - kot opažam na izpitih in v domačih
+nalogah - veliko bolj pri srcu funkcije, ki nekaj izpišejo, kot funkcije,
+ki vračajo rezultat. Tako bi jih mikalo, recimo, funkcijo za <code>vsoto</code>
+napisati tako, da bi na koncu namesto <code>return v</code> pisalo
+<code>print(v)</code>.</p>
+
+<p>Vendar to ni prav! S takšno funkcijo si nimamo kaj pomagati! Ne potrebujemo
+funkcije, ki <em>izpiše</em> vsoto; potrebujemo funkcijo, ki <em>vrne</em>
+vsoto, da bomo lahko s to vsoto še kaj počeli. Če jo bomo hoteli izpisati, bomo
+pač poklicali funkcijo in izpisali, kar vrne. Funkcija naj jo le izračuna. Si
+predstavljate, kako neuporabna bi bila funkcija <code>sin</code>, če bi le
+izpisala sinus, namesto da ga vrne? Bi si lahko pri programiranju topov z njo
+sploh kaj pomagali?</p>
+
+<p>To seveda ne pomeni, da funkcije ne smejo ničesar izpisovati. Smejo; nekatere
+so pač namenjene temu. Najbolj očiten primer takšne funkcije je očitno kar
+<code>print</code>.</p>
+
+<h2>Funkcije, ki ne vračajo ničesar</h2>
+
+<p>Vse funkcije v Pythonu vračajo rezultat. Če funkcija ne vrača ničesar, vrača
+ nič, torej <code>None</code>. To se bo zgodilo, kadar funkcija nima
+ <code>return</code> ali kadar se ta ne izvede.</p>
+
+<p>Napišimo, na primer, funkcijo, ki kot argument dobi seznam in vrne prvo sodo
+ število v njem.</p>
+
+<pre>def prvo_sodo(s):
+ for e in s:
+ if e % 2 == 0:
+ return e</pre>
+
+<p>In zdaj jo preskusimo:
+<pre>>>> prvo_sodo([1, 2, 3, 4, 5])
+2
+>>> prvo_sodo([1, 3, 5])
+>>> print(prvo_sodo([1, 3, 5]))
+None</pre>
+
+<p>Prvi klic je jasen: funkcija vrne 2. V drugem primeru pa nikoli ne pride do
+ <code>return</code>a, zato funkcija pač ne vrne ničesar. Ko smo jo
+ poklicali, se tudi ni nič izpisalo, saj Python, kadar ga poganjamo v
+ načinu za čvekanje, ne izpiše <code>None</code> ... razen, kadar ga k temu
+ prisilimo s <code>print</code>, kot smo storili v zadnji vrstici.</p>
+
+<p>Konstanta <code>None</code> se šteje za neresnično. To je praktično, saj jo
+lahko uporabljamo v pogojnih stavkih. Imejmo nek seznam <code>s</code> in
+izpišimo prvo sodo število ali pa povejmo, da v seznamu ni sodih števil.</p>
+
+<pre>sodo = prvo_sodo(s)
+if sodo:
+ print("Prvo sodo število je", sodo)
+else:
+ print("V seznamu ni sodih števil.")</pre>
+
+<p>Vendar moramo biti pri takšnem početju majčkeno previdni. Kaj, če je prvo sodo
+število v seznamu 0? Ker je tudi 0 neresnično, bo program v tem primeru napisal,
+da ni sodih števil. Pravilno bi bilo torej</p>
+
+<pre>sodo = prvo_sodo(s)
+if sodo != None:
+ print("Prvo sodo število je", sodo)
+else:
+ print("V seznamu ni sodih števil.")</pre>
+
+<p>Iz nekega razloga, ki ga bomo pojasnili čez dva tedna, pa običajno pišemo</p>
+
+<pre>sodo = prvo_sodo(s)
+if sodo is not None:
+ print("Prvo sodo število je", sodo)
+else:
+ print("V seznamu ni sodih števil.")</pre>
+
+
+<h2>Več rezultatov</h2>
+
+<p>Funkcija lahko vrača tudi "več rezultatov", tako kot tale funkcija, ki vrne,
+kvadrat in kub števila.</p>
+
+<pre>def kk(x):
+ return x ** 2, x ** 3</pre>
+
+<p>Pokličemo jo lahko takole.</p>
+
+<pre>kvad, kub = kk(5)</pre>
+
+<p>Pozoren študent je najbrž že spregledal mojo laž. V resnici funkcija
+vrača en sam rezultat, namreč terko in ob klicu funkcije to terko razpakiramo.
+Vendar nam o tem, tehničnem vidiku zadeve, ni potrebno razmišljati. Mirno se
+lahko vedemo, kot da smo dobili dve vrednosti.</p>
+
+<p>V tem primeru navadno ne pišemo oklepajev okrog terk. Funkcija bo delovala
+tudi, če pišemo <code>return (x ** 2, x ** 3)</code>, vendar to ni običajen
+zapis za vračanje dveh vrednosti.</p>
+
+<h2>Več returnov</h2>
+
+<p>Funkcija ima seveda lahko več <code>return</code>ov. Izvede se tisti, na
+ katerega naleti. En primer smo že videli (določanje praštevilskosti).
+ Naredimo še enega: funkcijo, ki vrne absolutno vrednost danega števila.</p>
+
+<pre>def abs(x):
+ if x < 0:
+ return -x
+ else:
+ return x
+</pre>
+
+<p>Funkcija ima torej dva <code>return</code>. Eden se izvede, če je število
+ negativno in drugi, če pozitivno.</p>
+
+
+<h2>Funkcije brez argumentov</h2>
+
+<p>Funkcija je lahko tudi brez argumentov. Tule je funkcija, ki nima argumentov,
+ vrne pa 42. Vedno.</p>
+
+<pre>def odgovor():
+ return 42
+</pre>
+
+<p>Tako funkcijo je potrebno tudi poklicati s praznim seznamov argumentov -
+oklepajev pa vseeno ne smemo pozabiti.</p>
+
+<pre>koliko = odgovor()</pre>
+
+<p>Malo pametnejši primer funkcije brez argumentov bi bila funkcija, ki
+ uporabniku zastavi račun in pove (s <code>True</code> ali
+ <code>False</code>), ali ga je pravilno rešil.</p>
+
+<pre>def uganka():
+ a = randint(2, 10)
+ b = randint(2, 10)
+ c = int(input("Koliko je {}x{}? ".format(a, b)))
+ return a * b == c</pre>
+
+<p>Z njo postane rešitev lanske domače naloge precej preglednejša.</p>
+
+<pre>from random import *
+from time import *
+
+konec = time() + 20
+tock = 0
+while time() < konec:
+ if uganka():
+ print("Pravilno.")
+ tock += 1
+ else:
+ print("Napačno.")
+print("Dosegli ste", tock, "tock")</pre>
+
+<p>Zdaj, ko znamo definirati funkcije, bo postalo naše življenje veliko lažje
+in preglednejše. Naši programi so, z vsem kar znamo, začeli postajati
+dolgi in razvlečeni. Zdaj jih bomo lahko razsekali v posamezne funkcije in se
+v njih tako lažje znašli.</p>
+
+</body>
+</html>
diff --git a/python/problems/functions/sl.py b/python/problems/functions/sl.py
index 7de0a40..7e00895 100644
--- a/python/problems/functions/sl.py
+++ b/python/problems/functions/sl.py
@@ -1,3 +1,3 @@
name = 'Funkcije'
-description = 'Pisanje in uporaba funkcij.'
+description = '<a target="_blank" href="[%@resource functions_sl.html%]">Pisanje in uporaba funkcij</a>'