summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Možina <martin.mozina@fri.uni-lj.si>2016-11-02 14:06:33 +0100
committerMartin Možina <martin.mozina@fri.uni-lj.si>2016-11-02 14:06:33 +0100
commit8540f7ca17b029b12bee6d8bef1c3e8911d688a4 (patch)
treea33c2f0a1f3da138bca9eff811d460fc65705ea5
parent656c66097e806b4c53646ea1fff3d8615426d304 (diff)
Text explaining modules and methods.
-rw-r--r--python/problems/functions_and_modules/methods_sl.html388
-rw-r--r--python/problems/functions_and_modules/modules_sl.html251
-rw-r--r--python/problems/functions_and_modules/sl.py5
3 files changed, 643 insertions, 1 deletions
diff --git a/python/problems/functions_and_modules/methods_sl.html b/python/problems/functions_and_modules/methods_sl.html
new file mode 100644
index 0000000..676ca5d
--- /dev/null
+++ b/python/problems/functions_and_modules/methods_sl.html
@@ -0,0 +1,388 @@
+<!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 kličemo metode</h1>
+
+<p>Funkcijam, ki smo jih srečevali doslej, smo, da so kaj naredile, morali dati
+ podatke, na katerih so delale. Funkcija <code>len</code> kot argument
+ zahteva seznam ali niz, katerega dolžino bi radi izvedeli. Funkcija
+ <code>input</code> kot argument želi niz z vprašanjem, ki bi ga radi
+ zastavili uporabniku. Razen argumentov, ki jih podamo, te funkcije nimajo
+ drugih podatkov (vsaj ne, da bi mi vedeli zanje).</p>
+
+<p>Ko smo se učili o seznamih, pa smo mimogrede naleteli na neko nenavadnost:
+ za dodajanje novega elementa v seznam nismo poklicali funkcije, ki bi ji
+ podali seznam in element (na primer <code>append(imena, "Ana")</code>),
+ temveč smo morali napisati ime seznama, ki mu je sledila pika in
+ <code>append</code>, kot argument pa smo navedli le element, ki smo ga
+ želeli dodati, torej <code>imena.append("Ana")</code>.</p>
+
+<pre>>>> imena = []
+>>> imena.append("Ana")
+>>> imena.append("Berta")
+>>> imena
+['Ana', 'Berta']</pre>
+
+<p><code>append</code> je očitno nenavaden, ne kličemo ga tako kot druge
+ funkcije. Funkcija <code>append</code> "pripada" seznamu; zato mu pravimo
+ <code>imena.append</code>. Naredimo še en seznam.</p>
+
+<pre>
+>>> teze = []
+>>> teze.append(55)
+>>> imena.append("Cene")
+>>> imena
+['Andrej', 'Branka', 'Cene']
+>>> teze
+[55]</pre>
+
+<p>Vsak seznam ima svoj <code>append</code>: <code>imena</code> imajo
+ <code>imena.append</code> in <code>teze</code> imajo
+ <code>teze.append</code>.</p>
+
+<p>Takšnim funkcijam pravimo <em>metode</em>. Klic <code>imena.append</code>
+ si predstavljamo, kot da <em>seznamu <code>imena</code> rečemo "dodaj si
+ element" <code>"Cene"</code></em> in klic <code>teze.append(55)</code>
+ pomeni, da <em>seznamu <code>teze</code> rečemo "dodaj si element"
+ <code>55</code></em>.</p>
+
+<p>Pika, <code>.</code> izraža nekakšno pripadnost, vsebovanost. Ko smo
+spoznali module, smo videli, da z <code>math.sqrt</code> pridemo do
+"math"ove funkcije z imenom "sqrt". Z <code>imena.append</code> zahtevamo
+"imenovo" metodo "append". In z <code>teze.append</code> "tezovo" metodo
+"append".</p>
+
+<p>Takšnih metod je še veliko: takole prosimo niz <code>ime</code>, naj nam
+ pove, koliko črk "n" vsebuje.</p>
+
+<pre>>>> ime = "Benjamin"
+>>> ime.count("n")
+2</pre>
+
+<p>Takole pa niz <code>fname</code> vprašamo, ali se konča s "torrent":
+
+<pre>>>> fname.endswith("torrent")
+True</pre>
+
+<p>Kako bi Benjamina spremenili v Benjamaxa? Težko: kot vemo, so nizi
+ nespremenljivi (tako kot terke; od vsega, o čemer smo govorili prejšnji
+ teden, lahko spreminjamo samo sezname). Pač pa lahko vprašamo niz, kako bi
+ bil videti, če "min" zamenjano z "max".</p>
+
+<pre>>>> ime.replace("min", "max")
+'Benjamax'</pre>
+
+<p>Metode niso povezane s tem, ali je niz shranjen v spremenljivki ali ne.
+ Metodo moremo poklicati tudi na nizu "kar tako".
+<pre>>>> "Maja".lower()
+'maja'</pre>
+
+<p>So z metodami obdarjeni samo nizi? Je to edinstven primer objektov v
+ Pythonu, ki imajo metode? Ne, nič ne bi moglo biti dalj od resnice! Skoraj
+ vsaka reč v Pythonu ima metode (ali vsaj nekaj podobnega). Celo običajna
+ števila imajo metode, čeprav zgolj tehnično in z zelo čudnimi imeni, kot
+ lahko vedoželjen študent hitro preveri:
+<pre>>>> (-231).__abs__()
+231</pre>
+
+<p>Med tipi, ki smo jih spoznali doslej, pa imajo uporabe vredne metode nizi
+ in seznami. V okviru predavanj ne bomo podrobneje spoznavali vse mogočih
+ podatkovnih tipov. Temeljiteje pa bomo pogledali metode nizov, seznamov
+ in podobnih reči, ki jih pri programiranju v Pythonu vsakodnevno
+ uporabljamo. Obenem bomo tako dobili vtis, kako te reči izgledajo. Najprej
+ nizi.</p>
+
+<h2>Metode nizov</h2>
+
+<p>Nekaj smo jih že spoznali: <code>count</code>, <code>replace</code> in
+ <code>lower</code>. Zadnja ima sestro, <code>upper</code>, ki vrne niz,
+ pri katerem so vse črke pretvorjene v velike črke.</p>
+<pre>>>> "Maja".lower()
+'maja'
+>>> "Maja".upper()
+'MAJA'</pre>
+
+<p>V žlahti z njima sta še (ne posebej uporabna) <code>capitalize</code> in
+ <code>title</code>.</p>
+
+<pre>
+>>> "benjamin".capitalize()
+'Benjamin'
+>>> "tole je stavek, ki ga bomo povelikocrkali po anglesko".title()
+'Tole Je Stavek, Ki Ga Bomo Povelikocrkali Po Anglesko'</pre>
+
+<p>Da ne bi kdo pozabil, za vsak slučaj še enkrat spomnimo: te metode ne
+ spreminjajo niza, temveč vračajo nove nize. Nizi ostanejo takšni, kot so
+ bili. Po tem primeru bi moralo biti jasno, kaj ne deluje in kako je
+ potrebno pisati, da bo delovalo.
+<pre>>>> s = "benjamin"
+>>> s
+'benjamin'
+>>> s.capitalize()
+'Benjamin'
+>>> s
+'benjamin'
+>>> s = s.capitalize()
+>>> s
+'Benjamin'</pre>
+
+<p>Metodo <code>count</code> smo že spoznali. Povejmo le še, da lahko išče
+ tudi daljše podnize, ne le posamezne znake.</p>
+
+<pre>>>> "Maja".count("a")
+2
+>>> "Maja".count("aj")
+1</pre>
+
+<p>Poleg <code>count</code> imamo tudi nekaj funkcij, ki povedo, kje v nizu
+ se nahaja določen podniz. Prvi sta <code>find</code> in <code>index</code>.
+ </p>
+
+<pre>>>> s
+'Benjamin'
+>>> s.find("jam")
+3
+>>> s.index("jam")
+3</pre>
+
+<p>Edina razlika med njima je v tem, kaj storita, če iskanega niza ni.
+ <code>find</code> vrne -1, <code>index</code> pa javi napako.</p>
+
+<pre>>>> s.find("maj")
+-1
+>>> s.index("maj")
+Traceback (most recent call last):
+ File "<interactive input>", line 1, in <module>
+ValueError: substring not found</pre>
+
+<p>Če se dani podniz pojavi večkrat, bosta funkciji vrnili indeks prve
+ pojavitve - razen, če jima z dodatnimi argumenti povemo, od kod naprej
+ naj iščeta. Poleg <code>find</code> in <code>index</code> obstajata še
+ funkciji <code>rfind</code> in <code>rindex</code>, ki iščeta s konca in
+ tako vrneta zadnjo pojavitev podniza v nizu.</p>
+
+<p>Mimogrede smo že omenili tudi preprosto, a zelo uporabno funkcijo
+ <code>endswith</code>, ki pove, ali se niz konča s podanim podnizom.
+ Poleg njega obstaja še <code>startswith</code>, ki pove ali se niz
+ <em>začne</em> z danim podnizom.</p>
+
+<p>Metode <code>ljust</code>, <code>rjust</code> in <code>center</code>
+ dopolnijo niz s presledki z leve, z desne ali z obeh strani, tako da je
+ dolg toliko, kot želimo. Takole napihnemo Benjamina na 15 znakov:</p>
+
+<pre>>>> s.ljust(15)
+'Benjamin '
+>>> s.rjust(15)
+' Benjamin'
+>>> s.center(15)
+' Benjamin '</pre>
+
+<p>(Še enkrat: te metode ne spreminjajo niza, temveč vrnejo nov niz!)</p>
+
+<p>Metoda <code>strip</code> naredi ravno nasprotno: odbije presledke (in
+ tabulatorje in znake za prehod v novo vrstico) na levi in desni strani
+ niza. <code>lstrip</code> in <code>rstrip</code> pospravita samo levo in
+ samo desno stran.</p>
+
+<pre>>>> s = ' asdf '
+>>> s.lstrip()
+'asdf '
+>>> s.rstrip()
+' asdf'
+>>> s.strip()
+'asdf'</pre>
+
+<p>Če se zdi ta metoda komu neuporabna, se moti. Zelo.</p>
+
+<p>Nizi imajo še veliko metod. Pogledali bomo le še dve najzanimivejši.</p>
+
+<p>Metoda <code>split</code> razbije niz na seznam podnizov, kakor jih ločujejo
+ presledki, tabulatorji in znaki za nove vrstice. (V prvem približku:
+ razbije jih na besede.)</p>
+
+<pre>>>> s = 'Metoda split razbije niz na seznam podnizov, kakor jih ločujejo presledki.'
+>>> s.split()
+['Metoda', 'split', 'razbije', 'niz', 'na', 'seznam', 'podnizov,', 'kakor', 'jih', 'locujejo', 'presledki.']</pre>
+
+<p>Presledkom, tabulatorjem in znakom za novo vrstico rečemo tudi <em>beli
+ prostor</em> (<em>white space</em>). Namesto glede na beli prostor lahko
+ <code>split</code> razbije niz tudi glede na kak drug znak, ki ga moramo
+ v tem primeru podati kot argument.</p>
+
+<pre>>>> "123-4123-21".split("-")
+['123', '4123', '21']
+>>> "123-4123-21".split("1")
+['', '23-4', '23-2', '']</pre>
+
+<p>Zadnja metoda, <code>join</code>, dela ravno obratno kot <code>split</code>:
+ združuje nize. Način, na katerega je obrnjena, je nenavaden, a če malo
+ razmislimo, vidimo, da drugače ne bi moglo biti.</p>
+
+<pre>>>> imena = ["Ana", "Berta", "Cilka", "Dani", "Ema"]
+>>> "".join(imena)
+'AnaBertaCilkaDaniEma'</pre>
+
+<p>Praznemu nizu, "", smo "naročili", naj združi nize iz podanega seznama. To
+ sicer ni videti preveč lepo, lepše bo, če jih združimo s kakim ločilom.</p>
+
+<pre>>>> "-".join(imena)
+'Ana-Berta-Cilka-Dani-Ema'
+>>> ", ".join(imena)
+'Ana, Berta, Cilka, Dani, Ema'
+>>> "--".join(imena)
+'Ana--Berta--Cilka--Dani--Ema'
+>>> " in ".join(imena)
+'Ana in Berta in Cilka in Dani in Ema'</pre>
+
+<p>Najlepše pa bo, če zadnjo vejico zamenjamo z "in".
+<pre>>>> ", ".join(imena[:-1]) + " in " + imena[-1]
+'Ana, Berta, Cilka, Dani in Ema'</pre>
+
+<p>Tule smo z <code>join</code> združili vse elemente razen zadnjega. K temu
+ nizu smo prišteli niz " in " in še zadnje ime s seznama.</p>
+
+<h2>Metode seznamov</h2>
+
+<p>Tako kot nizi imajo tudi seznami metodi <code>count</code> in
+ <code>index</code>, o katerih ne bomo izgubljali besed.</p>
+
+<p>Omenili smo že <code>append</code>, ki v seznam doda nov element. Pazite,
+ tole je pa zelo drugače kot pri nizih! Metoda <code>append</code> ne vrača
+ novega seznama, temveč v resnici spreminja seznam.</p>
+
+<p>Kako pa bi k nizu pripeli seznam? Tule nam <code>append</code> ne bo
+ pomagal: kar naredi, je povsem narobe.</p>
+
+<pre>>>> imena
+['Ana', 'Berta', 'Cilka', 'Dani', 'Ema', 'Fanci', ['Greta', 'Hilda']]</pre>
+
+<p>Kaj smo pa pričakovali? Metoda <code>append</code> doda k seznamu nov
+ element. Kar ji podamo kot argument, bo zadnji element seznama. Če torej
+ <code>append</code>u podamo seznam, bo seznam zadnji element seznama.</p>
+
+<p>Uporabiti moramo metodo <code>extend</code>.</p>
+
+<pre>>>> imena = ['Ana', 'Berta', 'Cilka', 'Dani', 'Ema', 'Fanci']
+>>> imena.extend(["Greta", "Hilda"])
+>>> imena
+['Ana', 'Berta', 'Cilka', 'Dani', 'Ema', 'Fanci', 'Greta', 'Hilda']</pre>
+
+<p>Mimogrede, isto bi dosegli tudi z</p>
+
+<pre>imena += ["Greta", "Hilda"]</pre>
+
+<p>Metode <code>extend</code> praktično ne uporabljamo, ker je nepotrebna.</p>
+
+<p>Metodi <code>insert</code> podamo dva argumenta, indeks in element, pa bo
+ vstavila element <em>pred</em> element s podanim indeksom (to si zapomnimo
+ takole: argument, ki ga podamo, bo indeks novega elementa).</p>
+
+<pre>>>> imena = ['Ana', 'Berta', 'Cilka', 'Dani', 'Ema', 'Fanci']
+>>> imena.insert(2, "PredCilka")
+>>> imena.insert(-2, "PreEma")
+>>> imena
+['Ana', 'Berta', 'PredCilka', 'Cilka', 'Dani', 'PreEma', 'Ema', 'Fanci']</pre>
+
+<p>Očitno deluje tudi indeksiranje s konca.</p>
+
+<p>Elemente seznama lahko odstranjujemo na tri načine. Prvega smo spoznali že
+ prejšnjič: z ukazom <code>del</code>. Še enkrat: <code>del</code> ni metoda
+ in prihaja iz povsem drugega vica, a vseeno ga pač omenimo, ker sodi
+ sem.</p>
+
+<pre>>>> imena
+['Ana', 'Berta', 'PredCilka', 'Cilka', 'Dani', 'PreEma', 'Ema', 'Fanci']
+>>> del imena[2]
+>>> imena
+['Ana', 'Berta', 'Cilka', 'Dani', 'PreEma', 'Ema', 'Fanci']</pre>
+
+<p>Metoda <code>pop</code> vrne element s podanim indeksom in ga pobriše s
+ seznama.</p>
+
+<pre>>>> ime = imena.pop(2)
+>>> ime
+'Cilka'
+>>> imena
+['Ana', 'Berta', 'Dani', 'PreEma', 'Ema', 'Fanci']</pre>
+
+<p>Priznati moram, da metode <code>pop</code> nisem še nikoli uporabil na ta
+ način - vsaj ne da bi se tega spomnil. V resnici namreč vedno pobiramo
+ elemente z začetka ali s konca seznama. Metodo <code>pop</code> lahko zato
+ pokličemo tudi brez argumentov: v tem primeru vrača zadnji element.</p>
+
+<pre>>>> imena
+['Ana', 'Berta', 'Dani', 'PreEma', 'Ema', 'Fanci']
+>>> imena.pop()
+'Fanci'
+>>> imena.pop(0)
+'Ana'
+>>> imena
+['Berta', 'Dani', 'PreEma', 'Ema']</pre>
+
+<p>Če bi hoteli, recimo, prestaviti prvi element na konec, bi napisali
+<code>imena.append(imena.pop(0))</code>.</p>
+
+<p>Tretji način je, da elementa, ki ga želimo odstraniti, ne določimo z
+ indeksom, temveč z vrednostjo - povemo, kakšen element bi radi odstranili.
+ Temu je namenjena metoda <code>remove</code>.</p>
+
+<pre>>>> imena.remove("Dani")
+>>> imena
+['Berta', 'PreEma', 'Ema']</pre>
+
+<p>Pri tem ne odstrani vseh takšnih elementov, temveč le prvega, na katerega
+ naleti, kakor lahko vidimo v spodnjem primeru.</p>
+
+<pre>>>> s = [7, 1, 2, 3, 4, 1, 1, 2]
+>>> s.remove(1)
+>>> s
+[7, 2, 3, 4, 1, 1, 2]</pre>
+
+<p>Metoda <code>s.copy()</code> naredi kopijo seznama <code>s</code>, tako
+kot da bi napisali <code>s = s[:]</code>.</p>
+
+<p>Metoda <code>s.clear()</code> ga
+izprazni, kar je isto kot <code>s[:] = []</code> in <em>ni isto kot</em>
+<code>s = []</code>. Razlika je tako prefinjena, da bo vredna posebnega
+predavanja.</p>
+
+<p>Le še dve metodi sta nam ostali. <code>reverse</code> obrne vrstni red
+ elementov v seznamu.</p>
+
+<pre>
+[7, 2, 3, 4, 1, 1, 2]
+>>> s.reverse()
+>>> s
+[2, 1, 1, 4, 3, 2, 7]</pre>
+
+<p>Zadnja je <code>sort</code>, ki uredi elemente po vrsti.</p>
+
+<pre>>>> s.sort()
+>>> s
+[1, 1, 2, 2, 3, 4, 7]</pre>
+
+<p>Metoda deluje nad vsakršnimi elementi, ki jih je mogoče primerjati - z njo
+ lahko uredimo seznam števil, nizov... Podamo ji lahko tudi kup argumentov,
+ ki pa jih v tem trenutku še nismo zmožni razumeti.</p>
+
+<p>Ne spreglejte razlike med metodami nizov in seznamov. Metode nizov vračajo
+nove nize; <code>s.replace("min", "max")</code> ni spremenil niza
+<code>s</code>, temveč vrnil nov niz. Metode seznamov spreminjajo seznam;
+<code>s.insert(2, "Ana")</code> ne vrne novega seznama, temveč spremeni
+<code>s</code>.</p>
+
+<h2>Metode terk</h2>
+
+<p>Terke imajo enake metode kot seznami, manjkajo jim le metode, ki spreminjajo
+ seznam. Teh pa, roko na srce, ni veliko. ;) Terke imajo le dve metodi:
+ <code>count</code> in <code>index</code>.</p>
+
+</body>
+</html>
diff --git a/python/problems/functions_and_modules/modules_sl.html b/python/problems/functions_and_modules/modules_sl.html
new file mode 100644
index 0000000..ec414ef
--- /dev/null
+++ b/python/problems/functions_and_modules/modules_sl.html
@@ -0,0 +1,251 @@
+<!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 uporabljamo module</h1>
+
+<p>Doslej smo spoznali le prgišče funkcij - <code>input</code>,
+ <code>len</code>, <code>sqrt</code>. V resnici pa skupaj s Pythonom dobimo
+ tisoče funkcij za vse mogoče reči, od pošiljanja pošte in kriptografije do
+ predvajanja zvoka in brskanja po datotekah .zip. Še večja gora funkcij
+ obstaja na spletu: karkoli si zamislite napisati, skoraj gotovo je nekdo
+ - če le gre za dovolj splošno reč - že potreboval kaj takšnega ter to tudi
+ napisal in vam dal na razpolago. Da se ne bi izgubili v gori funkcij (in
+ drugih reči), jih moramo nekako urediti.</p>
+
+<p>Modul je zbirka funkcij (in omenjenih drugih reči). Veliko modulov dobimo
+ že kar ob namestitvi Pythona, druge poberemo z interneta. Da bi lahko
+ uporabljali funkcije iz modula, moramo modul najprej uvoziti, kar storimo
+ z ukazom <code>import</code>, ki mu sledijo imena enega ali več modulov.
+ S Pythonom dobimo, recimo, modul z matematičnimi funkcijami, ki se imenuje
+ <code>math</code> in ga uvozimo takole:</p>
+
+<pre>import math</pre>
+
+<p>To praviloma storimo na začetku programa. Ko je modul uvožen, kličemo
+ njegove funkcije. Do funkcije, ki se nahaja v modulu, pridemo tako, da
+ napišemo ime modula, piko, in ime funkcije.</p>
+
+<pre>>>> math.sqrt(2)
+1.4142135623730951
+>>> math.log(2.71828)
+0.99999932734728203
+>>> math.log10(100)
+2.0</pre>
+
+<p>Primer druge reči, ki je v modulu, so konstante.</p>
+
+<pre>>>> math.pi
+3.1415926535897931</pre>
+
+<p>Drug primer modula je, recimo, modul s funkcijami, ki vračajo naključna
+ števila (in počnejo tudi druge naključne reči), <code>random</code>. Ta
+ ima, recimo, funkcijo <code>randint(a, b)</code>, ki vrne naključno število
+ med podanima vrednostima <code>a</code> in <code>b</code> (vključno z
+ <code>b</code>! Tu pravilo o tem, da <code>b</code> ni vključen, ne bi
+ imelo veliko smisla). Še dve zanimivi funkciji sta <code>choice</code>,
+ ki vrne naključno izbrani element seznama, in <code>shuffle</code>, ki
+ naključno premeša elemente seznama.</p>
+
+<pre>>>> import random
+>>> random.randint(10, 20)
+17
+>>> random.randint(10, 20)
+16
+>>> random.randint(10, 20)
+10
+>>> l = ["Ana", "Berta", "Cilka", "Dani", "Ema", "Fanci"]
+>>> random.choice(l)
+'Ana'
+>>> random.choice(l)
+'Dani'
+>>> random.shuffle(l)
+>>> l
+['Ana', 'Fanci', 'Dani', 'Cilka', 'Ema', 'Berta']</pre>
+
+<p><code>random.gauss(mu, sigma)</code> vrača naključna števila iz Gaussove
+ distribucije s podanim poprečjem <code>mu</code> in varianco
+ <code>sigma</code>. Tule je pet števil iz distribucije N(10, 3):</p>
+
+<pre>>>> for i in range(5):
+... print(random.gauss(10, 3), end=" ")
+...
+8.96174816507 8.79299353551 8.75687382602 9.49106109252 8.21589651224</pre>
+
+<p>Poglejmo še en modul, <code>os</code>. Ta vsebuje goro funkcij, povezanih
+ z datotekami in direktoriji (podatki o datotekah, preimenovanje, brisanje),
+ programi, ki tečejo na računalniku in drugo. Tako recimo funkcija
+ <code>os.listdir</code> vrne seznam vseh datotek v direktoriju, katerega
+ ime podamo kot argument.</p>
+
+<pre>>>> os.listdir("/Users/janez/Dropbox/Pedagosko/P1/2014/03 seznami")
+['blagajna.py', 'palindrom.py', 'stetje.py', 'domaca', 'razpakiranje.py',
+'zapiski.html', 'fibo.py', 'seznami.py', 'zip.py']</pre>
+
+<p>Funkcija <code>os.remove</code> pobriše datoteko s podanim imenom. Če bi
+ želeli v direktoriju <code>c:\d\kontrabant</code> pobrisati vse datoteke s
+ končnico <code>.pyc</code>, bi to storili takole:</p>
+
+<pre>for fname in os.listdir("/Users/janez/Dropbox/Pedagosko/P1/2014/03 seznami"):
+ if fname[-4:] == ".py":
+ os.remove("/Users/janez/Dropbox/Pedagosko/P1/2014/03 seznami" + fname)</pre>
+
+<p>Ob tej priliki povejmo, da ima v normalnih operacijskih sistemih vsak program
+ (bolj učeno: proces) nek "trenutni direktorij". Kadar imena direktorija
+ ne začnemo z / (ali \ ali c: ali čim podobnim na Windowsih), se ime nanaša
+ na datoteke oz. direktorije znotraj tega, trenutnega direktorija. Kakšen je
+ trenutni direktorij, nam pove funkcija <code>getcwd()</code> (get current
+ working directory), spremenimo pa ga z <code>os.chdir</code>. Kar smo
+ počeli zgoraj, bi se lahko napisalo tudi
+
+<p>Vse skupaj bi bilo morda lepše, če bi predtem zamenjali trenutni direktorij.</p>
+
+<pre>os.chdir("/Users/janez/Dropbox/Pedagosko/P1/2014/03 seznami")
+for fname in os.listdir("."):
+ if fname[-4:] == ".py":
+ os.remove(fname)</pre>
+
+<p>Ko smo ravno pri Windowsih, potarnajmo še, da ima znak \ v nizih v večini
+ programskih jezikov poseben pomen. Danes povejmo le, da moramo, če hočemo
+ dobiti \, napisati \\. Se pravi, ko bomo hoteli reči "c:\Users\janez", bomo
+ morali napisati "c:\\Users\\janez". Na srečo lahko tudi na Windowsih že
+ dolgo uporabljamo sicer običajnejši /.</p>
+
+<p>Če bi datoteke raje preimenovali kot brisali - recimo tako, da bi k njihovem
+ imenu dodali .bak, to storimo z <code>os.rename</code>, ki ji podamo staro
+ in novo ime datoteke.</p>
+
+<pre>for fname in os.listdir("."):
+ if fname[-4:] == ".py":
+ os.rename(fname, fname + ".bak")</pre>
+
+<p>Ob modulu <code>os</code> se lahko naučimo še nečesa zanimivega: modul
+ lahko vsebuje celo druge module. Tako modul <code>os</code> vsebuje modul
+ <code>path</code>. Modula <code>path</code> nam ni potrebno uvoziti,
+ dovolj je, da uvozimo <code>os</code>. Lahko pa ga uvozimo tudi takole</p>
+
+<pre>import os.path</pre>
+
+<p>Razlike pravzaprav (skoraj) ni.</p>
+
+<p>Modul <code>os.path</code> vsebuje različne funkcije povezane z imeni
+ datotek in njihovimi lastnostmi. Zanimiva je, denimo,
+ <code>os.path.splitext</code>, ki ji podamo ime datoteke in vrne terko z
+ dvema elementoma - osnovo imena in končnico. Pri tem ni potrebno, da
+ datoteka v resnici obstaja.</p>
+
+<pre>>>> os.path.splitext("/Users/janez/datoteka.txt")
+('/Users/janez/datoteka', '.txt')</pre>
+
+<p>Ker vemo, da lahko terko razpakiramo v dve spremenljivki, bomo pogosto rekli
+ kar</p>
+
+<pre>>>> osnova, koncnica = os.path.splitext("/Users/janez/datoteka.txt")</pre>
+
+<p>Gornji programček bi se torej še bolj lepo napisalo takole.</p>
+
+<pre>for fname in os.listdir("."):
+ if os.path.splitext(fname)[1] == ".py":
+ os.rename(fname, fname + ".bak")</pre>
+
+<p>Modul <code>os.path</code> ima še kup zanimivih funkcij, recimo
+ funkcijo, ki pove, ali določena datoteka oz. direktorij obstaja
+ (<code>os.path.exists</code>), funkcije, ki povedo ali določeno ime
+ predstavlja datoteko (<code>os.isfile</code>), direktorij
+ (<code>os.isdir</code>), povezavo (<code>os.islink</code>) ali kaj
+ drugega, kar je znano na Unixu, v Windowsih pa ne.</p>
+
+<h2>Uvažanje v globalni imenski prostor</h2>
+
+<p>Kaj je "imenski prostor" vam še ne nameravam, kaj "globalni", pa še ne
+ morem povedati. Vseeno se lahko naučimo, kako uvažamo vanj.</p>
+
+<p>Stvar je namreč jako preprosta. Morda se mi ne da stalno pisati
+ <code>math.sin</code>, <code>math.cos</code>, <code>math.pi</code>. Če bi
+ raje pisal le <code>sin</code>, <code>cos</code> in <code>pi</code>, bom
+ namesto z
+
+<pre>import math</pre>
+
+<p>modul uvozil z</p>
+
+<pre>from math import sin, cos, pi</pre>
+
+<p>S tem povem dve reči. Prva: zanimajo me le tri reči, <code>sin</code>,
+ <code>cos</code> in <code>pi</code>. Ostalih, recimo <code>sqrt</code>,
+ ne potrebujem in naj jih ne uvaža. (Dejanski mehanizem je malo drugačen,
+ tudi <code>sqrt</code> je v resnici uvožen, vendar ga ne vidim, a to ni
+ pomembno.) Druga: nočem, da se funkcije "skrivajo" v modulu
+ <code>math</code>, hočem jih "tu", torej, hočem jih klicati, ne da bi moral
+ prej pisati <code>math.</code>.</p>
+
+<p>Pogosto smo leni ali, še pogosteje, ne vemo točno, katere vse funkcije
+ bomo potrebovali, zato rečemo kar</p>
+
+<pre>from math import *</pre>
+<p>Zvezdica pomeni "vse funkcije" in hočemo jih tu, ne v <code>math</code>.
+ Za to obliko uvoza sem vam, da nam je bilo enostavneje, pokazal, ko smo
+ začeli streljati s topom.</p>
+
+<p>Temu načinu uvažanja se načelno izogibamo. Pogosto ga uporabljamo pri modulu
+ <code>math</code>, iz drugih modulov pa uvažamo le posamične funkcije
+ (<code>from random import randint</code>) ali pa pustimo modul kot modul
+ (<code>import random</code>).</p>
+
+<h1>Kako pišemo module</h1>
+
+<p>Napišimo program, ki bo vseboval konstanto <code>odgovor</code>,
+ki bo imela vrednost 42, in funkcijo, ki računa Fibonaccijeva števila.
+
+<pre>odgovor = 42
+
+def fibonacci(n):
+ a = b = 0
+ for i in range(n):
+ a, b = b, a+b
+ return a</pre>
+Program shranimo pod imenom fibo.py.</p>
+
+<p>To je to. V drugem programu lahko rečemo
+
+<pre>import fibo
+print("Odgovor je", fibo.odgovor)
+print("Deseto Fibonaccijevo število pa je", fibo.fibonacci(10))</pre>
+
+<p>Tudi vse ostale finte, na primer, <code>from fibo import odgovor</code>,
+ delujejo.</p>
+
+<p>Modul ni nič drugega kot program, ki ga uvozimo.</p>
+
+<p>Tudi vsi drugi programi, ki ste jih napisali doslej, so hkrati moduli:
+ lahko jih uvozite. Pazite le na tole: ko modul uvozimo,
+ se ta v resnici izvede, čisto tako, kot bi se izvajal program.
+ Vse, kar se v tem programu-modulu definira, ostane definirano in se
+ nahaja v modulovem imenskem prostoru. Vendar se zgodi tudi vse ostalo,
+ kar piše v modulu: če pri izvajanju naleti na <code>print("Foo")</code>
+ se bo ob uvozu modula izpisalo Foo. Če program-modul vsebuje klic funkcije
+ (in ne le definicij), se bo ta funkcija poklicala tudi ob uvozu.</p>
+
+<p>Kje Python išče module? Navadno v trenutnem direktoriju,
+ poleg tega pa še v drugih. Na Windowsih v, recimo,
+ <code>c:\Python34\lib\site-packages</code>.
+ Več o tem si lahko preberete v dokumentaciji.</p>
+
+<p>Tudi sicer ne bomo rinili prav globoko v module,
+ samo še eno stvar omenimo, da vas ne bo presenetila.
+ Ko boste prvič uvozili modul, se bo poleg datoteke s končnico .py
+ pojavila še ena, za enakim imenom, a končnico .pyc.
+ Python si vanjo "prevede" (pravzaprav bi smeli pisati brez narekovajev,
+ temu se v resnici reče prevajanje) v obliko, v kateri ga bo lahko
+ naslednjič hitreje uvozil. Pri manjših modulih se to ne pozna,
+ pri velikem številu velikih modulov pa. Če vas moti, jo lahko pobrišete;
+ drugič se bo pač spet pojavila ponovno.</p>
+
+</body>
+</html>
diff --git a/python/problems/functions_and_modules/sl.py b/python/problems/functions_and_modules/sl.py
index e4321ec..624a532 100644
--- a/python/problems/functions_and_modules/sl.py
+++ b/python/problems/functions_and_modules/sl.py
@@ -1,3 +1,6 @@
name = 'Funkcije in delo z moduli'
-description = 'Uporaba funkcij in delo z moduli (predvsem z nizi).'
+description = '''Uporaba funkcij in delo z
+ <a target="_blank" href="[%@resource modules_sl.html%]">moduli</a>.
+ Na primeru nizov spoznamo,
+ <a target="_blank" href="[%@resource methods_sl.html%]">kako kličemo metode</a>.'''