Te (in večino prihodnjih) zapiskov lahko pregledujete ter začasno spreminjate in poganjate programe v njih tudi tako, da (ne da bi morali kaj namestiti) uporabite Binder.
Za začetek bomo Python zagnali in uporabljali malo drugače kot kasneje. Odprli bomo Jupyter notebook, ki ste si ga (upam) namestili.
Odpremo ... bogve, kako je to po slovensko ... ukazna lupina? Pač Cmd, Shell, Konsole, Terminal, ITerm, bash, zsh ali kakorkoli se že to imenuje na vašem operacijskem sistemu in vašem računalniku). Pokazal se bo "ukazni pozivnik" (uh: prompt), kjer bo izpisano ime nekega direktorija (po novem moderno imenovanega "mapa") na vašem disku. Če ste na Windowsih in ta direktorij ni vaš "domači direktorij", se pravi, ne vsebuje vašega imena, vpišite
cd \Users\benjamin
vendar samo, če vam je (na tem računalniku) ime Benjamin. Če vam je kako drugače, vpišite kaj drugega. Če ne uporabljate Windowsov, pa je najbrž itak vse v redu.
jupyter notebook
izpisala se bo ta in ona nepomembna reč, potem pa se bo odprl brskalnik z vsebino vašega domačega direktorija.
Okna z ukaznim pozivnikom ne zaprite, saj bi s tem umrla tudi naša beležnica. Če vas moti, pa ga lahko zmanjšate.
Zgoraj desno poiščemo tipko New
, kliknemo in izberemo
Python 3
. Odpre se prazna beležnica.
Vtipkajmo 1 + 1
in pritisnimo Shift in Enter.
1 + 1
2
Tole bi znal izračunati vsak z minimalnim znanjem matematike. Poskusimo lahko tudi kaj bolj zapletenega.
8 * 7
56
1+2 * 3+1
8
Nič posebnega. Temu, kar smo vpisovali, pravimo izraz. Pri tem predmetu se sicer ne bomo ukvarjali s pravorečjem; teoretiki nas učijo o razliki med izrazom, stavkom in bogvečem še, sam pa se tule enkrat za vselej opravičujem, ker bom dal prednost praksi, ne terminologiji. Še definicijo pojma izraz bom prepustil kolegu Slivniku, ki bo nekatere od vas v tretjem letniku učil zanimivo snov o jezikih, prevajalnikih in sploh vsem).
Izraz bo za nas pač nekaj, kar se da izračunati (kar je ravnokar zaropotalo, je neki Alan Turing, ki se je z jabolkom v ustih obrnil v grobu). In gornje stvari se očitno dajo izračunati. In niti niso preveč zanimive.
Razen, morda, zadnjega izraza. V izrazih lahko uporabljamo presledke in to moramo - kot tudi sicer - početi po občutku. V zadnjem izrazu tega nismo počeli, zato je zapis zavajajoč. Python je dovolj pameten, da ve, da ima operator (še ena beseda, ki si jo zapomnimo!) množenja prednost pred operatorjem seštevanja. Kar smo napisali, se računa enako, kot če bi rekli
1+2*3+1
8
ali
1 + 2*3 + 1
8
ali
1 + 2 * 3 + 1
8
Nekoč se bomo dogovorili, da bomo uporabljali zadnjo obliko, dotlej pa postavljajte presledke, kamor vam veleva občutek, le nekaj se zmenimo: nikoli jih ne dajajte na začetek. Dokler vam naslednji teden ne bom rekel, da jih morate. Boste videli, zakaj.
Kakšni operatorji še obstajajo? Očitna sta še /
za
deljenje in -
za odštevanje. Dvojna zvezdica,
**
, pomeni potenciranje (mednju ne smemo napisati
presledka, **
je kot, recimo, ena beseda).
Operator %
izračuna ostanek po deljenju.
5 ** 2
25
3 ** 4
81
13 % 5
3
Potenciranje ima prednost pred vsem, kar poznamo doslej. Kadar je treba, pa lahko uporabimo oklepaje.
4 + 5) * 4 (
36
Če v isto celico zapišemo več računov, Notebook pokaže samo rezultat zadnjega.
1 + 3
5 * 6
8 - 2
6
Čisto druga reč pa je, če v vrstici ostane kak nezaprt oklepaj. V tem primeru Python ve (in pričakuje), da se izraz nadaljuje v naslednji vrstici.
4 + 2 * (3
(+ 8)-
2)
24
Tule ni lepo, a kdaj drugič nam bo prišlo še zelo prav, boste videli.
Pri množenju je nujno uporabiti zvezdico. Se pravi, pisati moramo
7 * (2 + 3)
in ne 7(2 + 3)
.
Za deljenje imamo poleg operatorja /
tudi
//
, ki deli celoštevilsko.
7 / 2
3.5
7 // 2
3
7 gre v 2 trikrat, in ena ostane. A celoštevilskega deljenja ostanek ne zanima.
Celoštevilsko lahko delimo tudi necela števila:
4.5 / 1.2
3.75
4.5 // 1.2
3.0
Pozornejšemu je padlo v oči še nekaj zanimivega: če delimo 7 z 2 dobimo 3, če 4.5 z 1.2, pa 3.0. Za prvo predavanje bi lahko to tudi preskočili, a se vseeno pomudimo: Python loči med celimi in necelimi števili. Lepše kot pri deljenju to pravzaprav vidimo pri seštevanju.
2.3 + 1.7
4.0
2 + 2
4
Če seštejemo realni števili 2.3 in 1.7 dobimo realno število 4.0. To
število je sicer "celo", vendar je tako zgolj "slučajno". Rezultat
seštevanja dveh realnih števil je realno število, in četudi je celo, ga
bo Python "interno" shranil kot necelo število in tudi pri izpisu dodal
.0
. Da se ve. Če seštejemo celi števili 2 in 2, dobimo celo
število 4.
Podobno je bilo pri deljenju. Rezultat (celoštevilskega) deljenja necelih števil je necelo število, rezultat celoštevilskega deljenja celih števil pa je celo število.
Kako hitro napredujemo! To, kar smo pravkar spoznali, so "podatkovni
tipi". Točneje, spoznali smo dva podatkovna tipa cela števila
in števila s plavajočo vejico. V angleščini se jima reče
integer in floating point number v Pythonu pa
int
in float
. Odkod ta čudna imena boste
nekateri izvedeli pri kakem drugem predmetu.
Vsaka reč v Pythonu je reč nekega tipa, in če je ta reč število, je
bodisi tipa int
bodisi float
. (So števila
lahko še kakega drugega tipa? Lahko, nekateri jeziki imajo celo kupe
številskih tipov. Vendar nas za zdaj ne brigajo.)
Neučakanega študenta morda pograbila radovednost. Kateri podatkovni tipi pa še obstajajo - razen številskih? Le malo naj počaka, kmalu bodo na vrsti.
Preden gremo naprej, samo opozorimo, kaj vas čaka v večini drugih
jezikov: v skoraj vseh drugih jezikih deljenje celih števil vrača celo
število; v Javi, ki se jo boste učili v drugem semestru, bo 7 / 2 enako
3. Obratno opozorilo, seveda, velja za tiste, ki že znate programirati
in ste morda vajeni drugače: v Pythonu izraz 7 / 2 vrne 3.5. Je to
pametno? Najbrž je: ko delimo, večinoma hočemo "pravo" deljenje in le
redko celoštevilskega. Še več, pri programiranju velikokrat naredimo
napako, ko brezskrbno delimo, ne da bi pomislili na to, s kakšnimi
števili - celimi ali ne - delamo. Avtorji Pythona so se zato odločili,
naj bo deljenje vedno "pravo", kadar hočemo celoštevilsko, pa moramo to
posebej povedati tako, da namesto /
uporabimo
//
.
V Notebooku je preprosto uporabiti rezultat zadnjega izračuna.
2 + 3
5
2 + _) * _ (
35
Vidimo? Tam kjer napišemo _
, se "vstavi" tisto, kar se
je izpisalo nazadnje. Tako (2 + _) * _
v bistvu pomeni
(2 + 5) * 5
. To lahko nadaljujemo.
+ 2 _
37
Zdaj je bil _
enak 35. In zdaj je 37
; to
lahko vidimo tudi tako, da napišemo "račun", ki ne vsebuje drugega kot
_
. :)
_
37
Kako pa pridemo nazaj, do rezultata izračuna 2 + 3
,
nekaj celic višje? En način, ki pa ni najbolj praktičen, je, da
uporabimo številko celice. Zgoraj piše In [19]
in
Out[19]
, torej gre za celico 19. Njen rezultat je v
_19
5
Torej lahko pišemo stvari kot
+ _20 _19
40
Kar počnemo zdajle, je posebnost Notebooka in nima veliko zveze s Pythonom (ali kakim drugim programskim jezikom). Pa še nepraktično je.
Če hočemo shraniti rezultat nekega izračuna za kasnejšo rabo, to storimo tako:
= 2 + 3 x
Temu pravimo prireditveni stavek. Rezultat izraza
2 + 3
smo poimenovali x
.
Tole zdaj je najbolj pomembna stvar v današnjem predavanju. Ne spreglejte je, čeprav je slišati trivialna, da ne bo kdaj kasneje postala kamen spotike (predvsem tistim, ki že znate programirati in si pod prirejanjem predstavljate nekaj drugega, kot v resnici je).
Da hočemo nekaj prirejati, povemo z enačajem (očitno). Na njegovi
desni je nek izraz - torej nekaj, kar se da izračunati. Včasih bo to
2 + 3
, včasih bo kaj veliko bolj zapletenega, pogosto pa bo
na desni strani samo številka, kot, recimo, v prirejanju
x = 42
. Python bo, tako kot v našem dosedanjem igranju z
njim, izračunal tisto na desni in dobil 5
ali
42
ali karkoli že.
Na levi strani enačaja je neko ime. Python bo temu imenu (recimo
x
) priredil tisto, kar je izračunal.
OK? Prireditveni stavek priredi imenu na levi strani enačaja rezultat izraza na desni.
Levo in desno od enačaja praviloma pišemo presledke, zaradi preglednosti.
Python tokrat ni izpisal ničesar v odgovor. Rezultat si je le
zapomnil, shranil ga je pod imenom x
. Kaj lahko počnemo s
tem x
? Lahko ga uporabljamo v drugih izrazih.
+ 7 x
12
** 2 x
25
13 % x
3
x
5
Kadar rečem x
, Python poišče, tisto, kar je priredil
x
-u. Če smo x
-u priredili 5 in rečemo
x + 7
, je to isto, kot če bi rekli 5 + 7
.
Temu x
Slovenci ponosno rečemo spremenljivka.
Angleži temu namreč pravijo variable, Madžari pa változó.
(Predvsem slednje ni posebej pomembno in ne pride v poštev kot izpitno
vprašanje, čeprav ne bo nobene škode, če veste. Koristi pa pravzaprav
tudi ne. ;))
(Medklic: da, temu bom govoril spremenljivka, a bolj prav bi bilo uporabljati besedo ime. Tudi Python temu reče name. Besedo spremenljivka bom uporabljal, ker smo programerji tako navajeni in železno srajco navade je težko sleči. Čez nekaj mesecev pa bomo izvedeli, kakšna je razlika in zakaj se sploh spotikati ob to.)
Spremenljivko lahko seveda uporabljamo tudi za računanje novih spremenljivk.
= x + 2
y y
7
Vidite, kaj smo storili tu? V prvi vrstici smo priredili vrednost
y
-u, v drugi smo to vrednost izpisali.
Spremenljivka pri programiranju (v večini jezikov) ne pomeni istega kot v matematiki. Spremenljivke v matematiki se, roko na srce, pravzaprav ne spreminjajo. V matematiki x ne more biti v eni vrstici 5, v naslednji pa 8. Pri programiranju pa lahko.
= 5
x x
5
= 8
x x
8
Še huje. Če matematiki ne bi znali programirati (pa navadno znajo in to dobro), bi jih utegnilo pretresti tole:
= 5
x = x + 2
x x
7
Napišite x = x + 2
pred profesorjem matematike, če si
upate!
Kako je x lahko enak x + 2? Saj ni. Ta enačaj ne
predstavlja enakosti, kot v matematiki, temveč
prirejanje. Ja? V drugi vrstici Python izračuna vrednost izraza
x + 2
, to je, 7
, in to priredi imenu,
spremenljivki x
. Izraz x = x + 2
torej pomeni,
preprosto, povečaj x
za 2
.
Tiste, ki že znajo vsaj malo programirati v kakem drugem jeziku, je morda zmotilo, da spremenljivk nismo nikjer deklarirali. (Tisti, ki jim beseda deklarirati ne pomeni ničesar, naj ostanejo v umestni nevednosti.) V Pythonu tega (skoraj) ne moremo narediti. Spremenljivka (točneje, ime) se pojavi, ko jo uporabimo, in izgine, ko je ne potrebujemo več.
Tem, ki že znajo programirati - posebej, če so uporabljali kak C# ali Javo - povejmo še, da se Pythonove spremenljivke tudi sicer bistevno razlikujejo od spremenljivk, ki so jih vajeni od ondod. Predvsem ni dobro, da so vas najbrž učili, da so "spremenljivke kot nekakšne škatlice". Če imamo
= 42
x = x y
imamo v nekaterih jezikih dve škatlici (in v obeh številko
42
), v nekaterih jezikih, med katerimi je tudi Python, pa
imamo eno samo škatlico z dvema imenoma, x
in
y
. Več o tem bomo izvedeli kasneje, ko bomo to zmožnejši
prebavljati in bomo videli tudi konkretno zmotnost ideje, da je
"spremenljivka kot nekakšna škatlica".
Ostali, tisti, ki niso še nikoli programirali, pa se sprašujejo nekaj drugega. Kakšna so lahko imena spremenljivk? Vedno le ena črka? Angleške abecede?
Takole: imena (angleško govoreči jim pravijo identifier) so
lahko poljubno dolga. Vsebujejo lahko črke angleške abecede, številke in
podčrtaj, _
, vendar se morajo začeti s črko ali podčrtajem,
s številko pa ne. Python, kot skoraj vsi drugi jeziki, razlikuje med
malimi in velikimi črkami: x
in isto kot X
. (V
resnici smemo uporabljati tudi šumnike in cirilico in kitajske pismenke,
vendar se tega ne navadite, ker je nezaželeno in ker tega ne boste mogli
početi v skoraj nobenem drugem jeziku kot v Pythonu, zato naj vam ne
pride v kri.)
Poleg tega obstaja še par dogovorov. Vsak jezik ima namreč poleg obveznih pravil tudi želeni slog. (Razen nekaterih, ki jih imajo več; najbolj notorično brezvladje je najbrž v C in C++.) Predvsem pa - in to vas bo kot računalnikarje prej ko slej zadelo - vsako resno podjetje določi pravila oblikovanja kode. Google, recimo, jih je predpisal za vse jezike, ki jih pogosteje uporablja (Google Style Guides). Vsi, ki programirajo v tem podjetju, se morajo teh pravil držati.
Imena naj se vedno začnejo z malo črko. Nekateri ste se učili drugih jezikov, kjer so navade drugačne. Ali pa so vas učili Python učitelji, ki nikoli niso brali pravil za Python. Kasneje bomo spoznali določene stvari, ki jih poimenujemo z veliko začetnico; dotlej pa - mala.
Če je ime sestavljeno iz več besed, jih ločimo s
podčrtajem, , na primer velikost_cevlja
. Obliko
velikostCevlja
boste videli le v starejših programih v
Pythonu.
Ime naj pove vsebino, ne vrste spremenljivke,
npr. pospesek = 9.8
. Spremenljivke ne poimenujte
stevilka
, ceprav morda res vsebuje številko. Ko bomo začeli
uporabljati sezname, vas bo veliko uporabljalo ime seznam
,
in če bodo v programu trije seznami, jih obste poimenovali
seznam1
, seznam2
, seznam3
. Da, to
vam bo zelo pomagalo razumeti, kaj ste shranili kam. To je približno
tako, kot če bi na knjigah pisalo "Knjiga" namesto, kaj je v njej. (Ni
pa zelo drugače od steklenic v Mercatorju, na katerih preprosto piše
"Vino".)
Kratka imena. Izogibajte se imen, kot so
a
, aa
, asd
... ki ne povedo nič.
Sicer me boste videli, da bom uporabljal kratka imena na predavanjih,
vendar le zato, ker bom tipkal v živo in nimate časa gledati, kako
tipkam imena_nekih_studentov
. Program, v katerem je deset
spremenljivk z imeni a
, b
, aa
,
a2
, a3
, a4
je nemogoče
brati.
Dogovorjena imena spremenljivk. Po drugi strani
pogosto uporabljamo kratka imena za "nepomembne" spremenljivke, ki
"živijo" le nekaj vrstic. Kot v matematiki bodo tudi tu spremenljivke z
imeni i
, j
, k
pogosto števci, se
pravi, nekaj, kar bo teklo od, recimo, 1 do 10. Po eni strani
neinformativno, po drugi pa vedno, ko vidimo i
,
j
, k
vemo, da gre za števec. e
bo
element kakega zaporedja. x
in y
bosta
argumenta (tako kot matematiki vedno rečejo sin(x)
). Imena
s
, t
, u
bodo pogosto seznami.
Nekateri imajo za seznam raje xs
(kot angleška množina
imena x
), saj je xss
potem seznam, ki vsebuje
sezname. To boste videli predvsem v nalogah na vajah. Ime s
bo sicer pogosto predstavljalo tudi besedilo.
Tega se vam niti slučajno ni potrebno zapomniti. Glejte, kako bom pisal na predavanjih in v zapiskih, pa se boste navadili.
Na to temo bi se dalo povedati še veliko in morda nekoč bomo. Za zdaj pa vam resno polagam na srce, kar je napisano tu. Predvsem tistim, ki že znate programirati in se vam zdi najlepše tako, kot delate zdaj. Meni se zdijo v Pythonu lepa Pythonova pravila, v JavaScriptu pa pravila JavaScripta.
Kdor razmišlja drugače, je kot Francoz, ki iz patriotizma namerno govori angleško s francoskim naglasom. Ali Štajerc, ki jo zavija po štajersko.
Vsi našteti dogovori (in še veliko podobnih bomo spoznali sproti) so samo dogovori. Če se jih ne držimo, bodo programi še vedno delovali. Pythonu je vseeno. Ni pa vseeno nam: če se držimo takšnih dogovorov, bodo naši programi preglednejši tako za nas, kot za druge, ki upoštevajo enaka pravila pisanja in bodo morali brati naše programe za nami.
"Vsak, kdor dela, dela tudi napake," se je jež poklapano opravičil krtači. Nobenega omemba vrednega kosa programa, daljšega od, recimo, 20 vrstic, ne napišemo brez vsaj ene resne napake. Pravzaprav tudi jaz, ki sem kar usposobljen programer, večine časa ne preživim ob programiranju, temveč ob iskanju napak v tem, kar sem pravkar sprogramiral. Začetni tečaji programiranja pa navadno ne posvečajo napakam nobene resne pozornosti. Tu te napake ne bomo ponovili, zato kar takoj naredimo nekaj napak.
Postavimo, najprej, a
na 7
in izračunajmo
a + b
.
= 7
a + b a
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[35], line 2
1 a = 7
----> 2 a + b
NameError: name 'b' is not defined
Ker je iskanje napak glavno opravilo programerja, se programski jeziki (točneje: programi, ki izvajajo programe, napisane v programskih jeziki :) trudijo biti karseda prijazni in poskušajo programerju čimbolj jasno povedati, kaj je zamočil.
Ko bomo programirali zares, bomo videli tudi daljša, ki jih bomo
težje razumeli, tole pa je preprosto:
name 'b' is not defined
. Pozabili smo definirati
b
, pozabili smo mu dati vrednost.
Kaj pa tole?
7 = a
Cell In[36], line 1
7 = a
^
SyntaxError: cannot assign to literal here. Maybe you meant '==' instead of '='?
Človek, vajen matematike, bi si mislil, da je a = 7
in
7 = a
eno in isto. V matematiki da, pri programiranju (v
normalnih jezikih) pa ne, saj enačaj pomeni prirejanje; v prvem primeru
priredimo a
-ju 7, v drugem primeru pa hočemo sedmici
prirediti a
, kar seveda ne gre. To ima natanko toliko
smisla, kot če bi napisali 1 = 2
. (Še več, Python nas bo po
prstih celo, če bomo napisali 1 = 1
. Ena je ena, to bo
ostala in se ne bo spremenila, niti v ena ne.) Sporočila o napaki tokrat
ne razumemo povsem, saj ne vemo, kaj je "literal", osnovno sporočilo,
"can't assign", pa je jasno.
Pridelajmo še eno napako.
True = 12
Cell In[37], line 1
True = 12
^
SyntaxError: cannot assign to True
Beseda True
ima poseben pomen in je ni mogoče
uporabljati kot spremenljivko. Takšnim besedam pravimo ključne besede,
ali, kot bi jim rekel John Kennedy, če bi bil še živ, keywords.
Tokrat je bil Python še prijazen, pri večini drugih ključnih besed pa ne
bo povedal kaj dosti več kot "nekaj je narobe". Poskusimo z dvema,
if
in in
:
if = 7
Cell In[38], line 1
if = 7
^
SyntaxError: invalid syntax
in = 7
Cell In[39], line 1
in = 7
^
SyntaxError: invalid syntax
Sporočilo "invalid syntax" pomeni, da smo napisali nekaj tako čudnega, da Python ne more uganiti, kaj smo mislili in nam lahko le pokaže tisto mesto, na katerem je dokončno obupal nad nami.
Morda je koga zaskrbelo, da nam bodo takšne, rezervirane besede v
stalno napoto. Bi se dalo videti spisek? Ne bo hudega. Python 3.7 jih
ima 35 (naraščanje je počasno: v zadnjih desetih letih je dobil le dve
novi) in zelo hitro bomo mimogrede spoznali in uporabljali skoraj vse.
Že od naslednjih predavanj naprej vam ne bo prišlo na misel, da bi
uporabili if
kot ime spremenljivke in še kak teden kasneje
vam bo stavek if = 1
videti grotesken. (Vsaj mene zabolijo
oči, ko ga pogledam in prsti se upirajo temu, da bi sploh natipkali kaj
takšnega.) Spisek? Ne bom vas strašil z njim, lahko pa si pomagate z
Googleom, če hočete. A ni potrebe.
Še dve sintaktični:
2 + 3 * 5)) (
Cell In[40], line 1
(2 + 3 * 5))
^
SyntaxError: unmatched ')'
5 +
Cell In[41], line 1
5 +
^
SyntaxError: invalid syntax
Pa še ena preprosta:
= 5
a 7 / (a - 5)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Cell In[42], line 2
1 a = 5
----> 2 7 / (a - 5)
ZeroDivisionError: division by zero
Ko program izpiše napako jo moramo razumeti in potem popraviti program. Tule, ko pišemo le čisto kratke izraze, se o tem ni kaj dosti pogovarjati. Ko gre za daljše programe, pa programa, ki ne deluje, temveč javlja kako napako, študenti pogosto ne poskušajo popraviti, temveč ga le spreminjajo, dokler ne začne delovati. To je slabo iz dveh razlogov. Prvi je, da je to neučinkovito. Python se res trudi, po najboljših močeh, da bi povedal, kaj je narobe. Veliko učinkoviteje je razumeti, kaj nam hoče povedati in ukrepati, kot pa brskati kot slepa kura. Sploh zato, ker so programi pri tem predmetu kratki in se jih mogoče da popraviti na slepo srečo. V resničnem življenju pa so daljši in je, prosim, verjemite mi, res potrebno razumeti napake.
Drugi razlog, da slepo popravljanje napak ni dobra ideja, je, da utegnemo na ta način le obiti simptome, neposreden vzrok za napako. Prava napaka pa lahko ostaja nekje drugje, skrita, nepopravljena.
Znanje branja napak je osnovna veščina programerja. Pomembno je, da jo obvladate.
Tako kot spremenljivke, ki v programiranju ne pomenijo čisto istega
kot v matematiki in v programiranju ne pomenijo čisto istega, tudi
beseda funkcija (Rihanna bi rekla function, če bi
znala programirati, v kar pa dvomim) ne pomeni povsem istega. Videti pa
je zelo podobno. Imamo, recimo, funkcijo abs
, ki izračuna
absolutno vrednost števila.
abs(-2.8)
2.8
Ali pa pow
, ki naredi isto kot operator
**
.
pow(2, 3)
8
Ob pow
omenimo - predvsem za tiste, ki že znajo
programirati v kakem drugem jeziku -, da je bolj običajno pišemo
2 ** 3
in ne pow(2, 3)
. Funkcija
pow
(okrajšava za angleški power) ima svoje super
powers in uporabljamo jo le takrat, ko jih potrebujemo.
Za razliko od matematikov, ki na funkcijo gledajo, kot da ima
določeno vrednost pri določenih parametrih, računalnik izračuna
vrednost funkcije, za kar moramo poklicati funkcijo. Se
pravi, v zadnji vrstici smo poklicali funkcijo pow
in ji podali dva argumenta, 2 in 3. Funkcija je
izračunala vrednost in jo vrnila.
Tudi klic funkcije, pow(2, 3)
, je izraz. Kot katerikoli
drugi izraz lahko tudi pow
in abs
nastopata
kot del izraza.
pow(2, 3) + 2) / 5 (
2.0
pow(2, 3) + abs(-2)
10
In argumenti funkcij so lahko prav tako izrazi.
= 1
x = pow(abs(-2), x * 3)
yy yy
8
Funkcije so v resnici zelo pomembna reč. Python ima milijone in milijone funkcij (ne pretiravam, samo en detajl sem zamolčal). Za vsako reč, ki si jo zamislite, obstaja funkcija. Obstaja funkcija, ki bo, če jo pokličete, poslala mail osebi, katere naslov podate kot argument in z vsebino, ki jo podate kot argument. Obstaja funkcija, ki izriše ali pokaže sliko. Funkcija, ki odpre Excel in funkcija, ki piše po njem. S Pythonom lahko naredimo karkoli, le ime funkcije moramo poznati. (Kot rečeno, izpuščam detajle.)
Nas še vedno muči radovednost o tem, kakšne podatkovne tipe, poleg številskih, še imamo? Ker radovednost ni lepa čednost, jo bomo najlažje odpravili tako, da jo potešimo. Vsaj malo. ("Skušnjavo najlažje premagaš tako, da ji podležeš," je modroval Oscar Wilde. Res pa je, da so ga kasneje aretirali in zaprli.) Spoznajmo vsaj še en bolj zapleten podatkovni tip: niz.
Niz ali, kot mu pravijo Avstralci, string (oprostite mi boste morali, da bom pogosto uporabljal angleške izraze; pa mi pokažite, lepo prosim, zidarja, ki ne uporablja vaservage in plajbe temveč vodno tehtnico in svinčnico, pa se bom tudi jaz discipliniral), je zaporedje znakov. Aha, kaj pa je to znak? Znaki so črke, številke, ločila in take stvari. Nize moramo vedno zapreti v narekovaje, bodisi enojne (') bodisi dvojne ("). Uporabiti smemo take, ki so bolj praktični in tudi Python bo izpisoval tako, kot se mu bo zdelo bolj praktično.
'Tole je primer niza.'
'Tole je primer niza.'
"Tole je pa še en primer niza."
'Tole je pa še en primer niza.'
Tudi ko smo niz zaprli v dvojne narekovaje, je Python izpisal enojne. V resnici mu je vseeno. (V nekaterih jezikih imajo različni narekovaji povsem ali pa vsaj nekoliko različen pomen. V Pythonu ne, pač pa različne pomene, kot bomo videli, dosežemo tako, da prednje postavimo kak primeren znak.)
Tudi nize lahko priredimo spremenljivkam.
= "Jutri bosta matematika pa dež"
napoved napoved
'Jutri bosta matematika pa dež'
Celo seštevamo jih lahko.
"Jutri bosta " + "matematika" + " pa " + "dež"
'Jutri bosta matematika pa dež'
Ali pa oboje
= "Jutri bosta "
napoved_zac = "matematika"
mat = "dez"
dez + mat + " pa " + dez napoved_zac
'Jutri bosta matematika pa dez'
Kako zapleten račun! Predvsem ne spreglejte, da smo dali besedo "pa"
pod narekovaje, saj so napoved_zac
, mat
,
dez
spremenljivke (ki so v resnici nizi),
" pa "
pa je niz kar tako. To je nekako tako, kot če bi, ko
smo se igrali s številkami, pisali
= 1
x = 3
y + 2 + y x
6
V zadnji vrstici sta x
in y
sta
spremenljivki (ki sta v resnici številki), 2
pa je številka
kar tako.
Kaj pa, če bi slučajno pozabili narekovaje?
+ mat + pa + dez napoved_zac
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[54], line 1
----> 1 napoved_zac + mat + pa + dez
NameError: name 'pa' is not defined
Jasno? Brez narekovajev je pa
ime spremenljivke - in to
takšne, ki še ni definirana. To je tako, kot če bi namesto
= "Benjamin" ime
kar je pravilno, rekli
= Benjamin ime
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[56], line 1
----> 1 ime = Benjamin
NameError: name 'Benjamin' is not defined
Ali pa:
= Jutri bosta matametika pa dež napoved
Cell In[57], line 1
napoved = Jutri bosta matametika pa dež
^
SyntaxError: invalid syntax
Tule računalnik trpi še bolj. Ne le, da so Jutri
,
bosta
, matematika
, pa
in
dež
nedefinirane spremenljivke (ker so pač brez
narekovajev),računalnik tudi nima pojma, kaj hočemo pravzapravz početi z
njimi, čemu mu naštevamo imena nekih spremenljivk. Jih hočemo sešteti
ali zmnožiti ali kaj? Kot vedno, kadar računalniku napišemo kaj zares
zmedenega, nam zastoka le "syntax error" in pokaže mesto, kjer se je
dokončno izgubil.
Gornje je tako, kot da bi rekli
= 1
x = 2
y = 3
z x y z
Cell In[58], line 4
x y z
^
SyntaxError: invalid syntax
Ubogemu računalniku pač ni jasno, kaj bi z x
,
y
in z
ter zakaj mu jih naštevamo.
Tiste, ki so ob vpisu na fakulteto nihali med računalništvom
in slavistiko, je nemara zbodlo, da sem pisal "Jutri bo matematika pa
dež". Mar ne bi bilo lepše (in bolj prav) "matematika in dež". Ponovite
vse, kar smo napisali zgoraj, z in
, pa boste videli, čemu.
Za jezikovno okornost se seveda opravičujem, ampak z in
tale primer ne bi deloval.
Zakaj pa smo prejle rekli, da uporabimo tiste narekovaje, ki so bolj praktični? Čemu bi bili kakšni narekovaji bolj praktični od drugih?
"Cesar vpraša nekoliko nevoljen: "Kaj neki?""
Cell In[59], line 1
"Cesar vpraša nekoliko nevoljen: "Kaj neki?""
^
SyntaxError: invalid syntax
Ni potrebno biti posebno pameten, da vidimo, kaj ga je (namreč Pythona, ne cesarja) onesrečilo tokrat. Ko vidi prvi narekovaj, ve, da gre za niz. Ko pride do naslednjega narekovaja, se niz, tako méni, niz konča. In potem se seveda zmede, ker nizu sledi nekaj, kar ni podobno ničemur. Zdaj pa poskusimo z enojnimi narekovaji.
'Cesar vpraša nekoliko nevoljen: "Kaj neki?"'
'Cesar vpraša nekoliko nevoljen: "Kaj neki?"'
Ker se niz začne z enojnim narekovajem, se bo s takim tudi končal in vsi dvojni narekovaji znotraj niza so samo znaki kot katerikoli drugi - tako kot recimo dvopičje in vprašaj. O tej temi bi lahko napisali še marsikaj, vendar se za zdaj ustavimo.
Da se reč usede, meditirajmo ob naslednjih vrsticah:
= 1 + 1
a = "1 + 1"
b = "1" + "1" c
Kakšne so po tem vrednosti spremenljivk a
,
b
in c
? Sploh pa, je vse troje legalno ali pa
bo Python spet kaj stokal?
V prvo nimamo dvomov, vrednost a
mora biti enaka 2 (in
tudi je).
a
2
Drugo? "1 + 1"
je niz; spremenljivki b
smo
priredili niz "1 +1"
, torej vsebuje ta niz. In ne niza 2?
Ne, nihče mu ni naročil, naj poskuša izračunati, koliko je 1 + 1, tako
kot pravzprav tudi v ime = "Benjamin"
ne poskuša
izračunati, "koliko" je Benjamin. "1 + 1"
je niz, kot vsak
drugi, čeprav je slučajno podoben računu.
b
'1 + 1'
Najbolj zanimivo je tretje. Preden razrešimo vprašanje, se vprašajmo nekaj drugega. Recimo
= "Ana"
ana = "Benjamin"
benjamin = ana + benjamin r
Kaj dobimo, če seštejemo Ano in Benjamina. (Tončka? Brez duhovičenja,
to so resne reči.) Spremenljivka r
bo imela vrednost
"AnaBenjamin"
. Glede tega smo si menda enotni, ne? (Ako kdo
misli, da bomo dobili "Benjamin Ana"
, saj smo tudi poprej
imeli presledke ob oni študijsko-vremenski napovedi, naj pozorno
pregleda, kaj smo pisali ondi: vse presledke smo napisali sami.)
No, potem pa vemo: ko seštejemo niza "1" in "1" niz "11". "1" in "1" torej ni "2", temveč "11".
c
'11'
Nikar ne zamudimo priložnosti za še eno napako!
1 + "1"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[66], line 1
----> 1 1 + "1"
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Seštevanje je operacija, zato tistemu, kar je levo in desno
od nje pravimo operanda. Sporočilo pravi, da operator
+
ne podpira operandov tipov int
in
str
(str
je podatkovni tip, ki predstavlja
nize). Dve števili ali dva niza bi znal sešteti, te kombinacije pa ne.
Mimogrede, obratni vrstni red da nekoliko drugačno sporočilo:
"1" + 1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[67], line 1
----> 1 "1" + 1
TypeError: can only concatenate str (not "int") to str
Stikanje (concatenation) je le drugo ime za seštevanje nizov; sporočilo pravi, da ne moremo stakniti niza in števila. Na to napako boste v prvih dveh tednih vaj pogosto naleteli, tako da bodite pripravljeni. Kasneje bomo delali drugačne stvari in bo šlo mimo.
Ker nam bo prišlo vsak čas prav, povejmo, kako iz niza dobimo
število. Recimo, torej, da imamo a = "1"
in
b = "2"
. Radi bi ju sešteli - vendar zares, tako da bomo
dobili 3, ne "12". Za to ju moramo najprej (ali pa sproti) spremeniti v
števili. Iz niza dobimo število tako, da pokličemo "funkcijo"
int
ali float
; obe funkciji pričakujeta kot
argument niz, ki vsebuje neko število in kot rezultat vrneta celo
(int
) ali realno (float
) število. (Tole bi se
spodobilo in bilo pravično povedati: int
in
float
v resnici nista funkciji, temveč nekaj drugega, a za
potrebe prvih toliko in toliko predavanj, se bomo držali Pythonovega
načela "Če hodi kot raca in gaga kot raca, potem je raca", ki bo postalo
pomembno proti koncu semestra; če se obnašata kot funkciji, ju bomo brez
slabe vesti oklicali za funkciji.)
int("42")
42
float("42")
42.0
Kar želimo, storimo na tri načine, vsak bo poučen po svoje. Prvi:
= "1"
a = "2"
b
= int(a)
aa = int(b)
bb + bb aa
3
Naredili smo dve novi spremenljivki, aa
in
bb
, ki vsebujeta vrednosti a
in
b
, pretvorjeni v števila. Nato ju seštejemo.
Drugi:
= "1"
a = "2"
b
= int(a)
a = int(b)
b + b a
3
Tole je podobno kot prej, le da smo povozili stare vrednosti
a
in b
z novimi, številskimi, namesto da bi
števila zapisovali v druge spremenljivke.
Samo za tiste, ki že znate programirati, a ne v Pythonu: po
izkušnjah iz preteklih let, se tule začne polovica predavalnice praskati
po glavi, pogumnejši pa se začnejo oglašati, da je Python čuden jezik
oziroma, z generaciji lastnejšimi besedami, kr neki. To, da
tipov spremenljivk ni potrebno deklarirati, so še nekako požrli. Ampak
tole tule je pa višek, pravijo: je a
tipa niz ali število?
No, na srečo se lahko skličem na to, kar sem polagal v srce ob
prireditvenem stavku: prirejanje priredi imenu neko vrednost. Predvsem
pa Python nima spremenljivk v takem pomenu besede, kot ste jih vajeni iz
Jave, C# ali C++, temveč ima imena za objekte. Prirejanje
a = "1"
priredi imenu a
niz "1". Prirejanje
a = int(a)
priredi imenu a
številko 1. Ime
a
se po tem pač ne nanaša več na nek niz temveč na neko
število. Python nima spremenljivk, temveč imena. In imena nimajo
tipov.
Tretji:
= "1"
a = "2"
b
int(a) + int(b)
3
Ker je int
funkcija, lahko nastopa v izrazu; potrebe, da
bi prepisovali številke v kake nove ali stare spremenljivke, niti
ni.
Doslej smo z računalnikom komunicirali tako, da smo tipkali ukaze v
ukazno vrstico in če je imela reč kak rezultat (kot ima izraz
1 + 1
rezultat 2
), ga je računalnik izpisal.
Ukazna vrstica nam v Pythonu pogosto pride prav za kakšna preskušanja,
ko programiramo zares, pa komunikacija z uporabnikom poteka drugače. Če
hočemo, da računalnik kaj izpiše, mu moramo to posebej reči. Se pravi,
ko bomo programirali, ne bomo napisali le 1 + 1
temveč
"izpiši, koliko je 1 + 1".
Rekli smo, da funkcije pri programiranju niso nekaj takšnega kot
funkcije v matematiki: funkcije v matematiki imajo določeno vrednost pri
določenih argumentih (še huje, matematiki pravijo, da so funkcije
pravilo, ki vsakemu elementu kodomene funkcije določi ... uh, pustimo).
"Naše" funkcije pa nekaj delajo in včasih vrnejo kakšen rezultat, recimo
številko ali niz ali kaj tretjega. Ena od teh funkcij je namenjena
izpisovanju: če jo pokličemo, izpiše tisto, kar smo ji dali kot
argument. Imenuje se print
. Za razliko od, recimo,
abs
, ki zahteva en argument, namreč poljubno število, in
vrne njegovo absolutno vrednost, ali pow
, ki hoče natanko
dva argumenta, lahko damo print
u poljubno število
argumentov - številke, nize ali še kaj tretjega -, pa jih bo lepo
izpisala.
print(1 + 1, 27, "benjamin")
2 27 benjamin
print(napoved_zac, mat, "pa", dez, "in", 18, "stopinj")
Jutri bosta matematika pa dez in 18 stopinj
Med reči, ki jih izpiše, bo print
, če ne zahtevamo
drugače, postavil presledke.
Druga funkcija, ki nam bo prišla prav, prosi uporabnika, da vpiše kako reč. Kot argument pričakuje niz, vprašanje, ki ga želimo zastaviti uporabniku. Kot rezultat "izračuna" vrne niz, ki ga je vpisal uporabnik.
= input("Geslo? ") geslo
Geslo? qwerty123
geslo
'qwerty123'
Sestavimo tole: računalnik naj uporabnika prosi za temperaturo v Celzijevih stopinjah in računalnik mu bo izpisal, koliko je to v Kelvinih in koliko v Fahrenheitih. Iz Celzijev dobimo Kelvine tako, da jim prištejemo 273.15, Fahrenheite pa tako, da jih pomnožimo z 9/5 in prištejemo 32 (kogar zanima še kaj, naj pogleda na Wikipedijo.
= input("Temperatura [C]? ")
temp_C = temp_C + 273.15 temp_K
Temperatura [C]? 25
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[78], line 2
1 temp_C = input("Temperatura [C]? ")
----> 2 temp_K = temp_C + 273.15
TypeError: can only concatenate str (not "float") to str
Eh. Funkcija input
vrne niz, ki ga je
vpisal uporabnik. Četudi utegne ta izgledati kot številka, je še vedno
niz in k nizom ni mogoče prištevati števil. Kot smo videli, lahko
storimo troje: naredimo novo spremenljivko, na primer,
temp_Cf = float(temp_C)
, povozimo staro s
temp_Cf = float(temp_C)
ali pa pretvorbo opravimo kar
sproti, tako da računamo temp_K = float(temp_C) + 273.15
.
Izmed naštetih možnosti se odločimo za četrto in niz pretvorimo, čim ga
uporabnik vpiše. Ponovimo torej vso vajo.
= float(input("Temperatura [C]? "))
temp_C = temp_C + 273.15
temp_K = temp_C * 9 / 5 + 32
temp_F print(temp_C, "C je enako", temp_K, "K ali", temp_F, "F")
Temperatura [C]? 25
25.0 C je enako 298.15 K ali 77.0 F
V začetku smo rekli, da bomo Python za začetek poganjali drugače kot sicer. Na koncu ga le poženimo tako, kot ga bomo sicer, vmes pa se še kaj naučimo.
Ko smo vtipkali jupyter notebook
smo na računalniku
zagnali lokalni spletni strežnik. Ker je lokalni, je dosegljiv
le z našega računalnka (da bi bilo drugače, bi se morali posebej
potruditi). Ta spletni strežnik omogoča pisanje besedila (kar, recimo,
ravnokar počnem) in izvajanje koščkov kode v Pythonu. Beležnica je
uporabna, no, kot beležnica. Vanjo si lahko kaj zapišemo, to shranimo,
delimo z drugimi, objavljamo na spletu. Vanjo lahko dodajamo slike,
znotraj nje lahko (s Pythonom) rišemo grafe.
Pri tem predmetu nam bo služila za zapiske. Če jih boste naložili na svoj računalnik, jih boste lahko dopolnjevali, se igrali s programi, zapisanimi v njih... Programirali pa bomo pretežno v razvojnih okoljih.
Tega, kar razlagam tu, pri tem predmetu ne bomo počeli. Koristno pa je povedati, da bolj razumemo, kaj se dogaja in kako stvari delujejo.
Programe pišemo v datoteke. Odprimo primeren urejevalnik: vsem priporočam, da si v take namene namestite Visual Studio Code, sicer pa so z MS Windows pride Notepad, na macOS pa, recimo, TextEdit. Razni Word in Pages za to niso primerni, ker datoteke ne shranijo v pravi obliki.
Odprevši urejevalnik vanj skopiramo gornji program.
Reč shranimo pod imenom, recimo, "temperature.py". (Če to resno kdo dela v Notepadu, naj pri shranjevanju dejansko natipka tudi narekovaje, sicer mu bo Notepad shranil temperature.py.txt.)
Spet odpremo ukazno lupino (Cmd, Terminal ...) in vtipkamo
cd
in ime direktorija, kamor smo shranili temperature.py,
potem pa (na Windowsih)
c:\python310\python.exe temperature.py
(ali nekaj takega),
drugje pa python3 temperature.py
.
Z c:\python310\python.exe
oziroma s python3
poženemo program Python. Program Python zna brati in izvajati programe v
Pythonu. S temperature.py
mu povemo ime datoteke s
programom, ki naj ga izvede. Program Python lepo, vrstico za vrstico
bere datoteko in počne, kar piše v njej.
V resnici tudi beležnica počne nekaj podobnega. Avtorji beležnice
niso napisali programa, ki "razume" naše ukaze, kot je bil
float(input("Temperatura:"))
in tako naprej. Ne, beležnica
(na nek način) pošilja naše programe programu Python in ta jih izvaja.
Tisti na nek način pa zato, ker je tudi beležnica sama napisana
v Pythonu in ga uporabi nekako ... bolj interno, ne prek, bognedaj,
ukazne lupine ali česa podobnega.
Namen gornjega je bil predvsem povedati, da program v Pythonu ni nič
drugega kot datoteka z običajnim besedilom in da program
python
, ki izvaja programe v jeziku Python, ne dela
drugega, kot da prebere takšno datoteko in izvede navodila, napisana v
njej.
Pisati programe z Notepadom bi bilo duhamorno. Notepad nam ne bi pomagal ne pri pisanju ne pri iskanju napak, saj nima pojma o Pythonu. Poleg tega bi morali programe stalno shranjevati in jih poganjati iz ukazne lupine.
Za programiranje uporabljamo razvojna okolja. Razvojna okolja so programi, ki so v osnovi urejevalniki besedil, kot Notepad, vendar nam pomagajo pri delu tako, da smiselno obarvajo kodo, da je preglednejša, dopolnjujejo imena spremenljivk in funkcij, sami dodajo kak delček programa, sproti opozarjajo na morebitne napake, poleg tega pa lahko program, ki ga pišemo, poženemo kar iz razvojnega okolja.
Zadnje sicer ni čisto res. Razvojna okolja (vsaj za Python) tipično ne izvajajo programa sama, temveč pokličejo program Python - glej prejšnji razdelek :).
Pri tem predmetu bomo kot razvojno okolje uporabljali PyCharm, kdor želi, pa lahko uporablja tudi preprostejše urejevalnike.
Kdor želi kaj preprostega, bo vzel Visual Studio Code. Če namestimo še primerne dodatke, nam pomaga oblikovati kodo, iskati pozabljena imena spremenljivk v dolgih programih, pokazati dokumentacijo posameznih funkcij in, do neke mere, poganjati programe. Sam v njem pišem kratke programčke v Pythonu, za resno programiranje pa uporabljam PyCharm, tako da vam pri morebitnih zapletih z Visual Studiom Code ne bom v veliko pomoč.
Starejši mački prisegajo na starejše urejevalnike, kot so emacs in vi oz. vim. Tudi med študenti se vsako leto najde kakšen in nihče mu ne brani. Tudi mazohizem je v sodobni družbi popolnoma sprejeta orientacija.
Najbrž najbolj popularno profesionalno okolje za razvoj programov v Pythonu je PyCharm. Gre za komercialno orodje, vendar ga razvija podjetje, ki je zelo naklonjeno tudi odprti kodi, predvsem pa imajo zastonjsko različico, ki ji prav nič ne manjka. Zato izjemoma nimamo slabe vesti, ker študente navajamo na komercialne programe. Predvsem pa je PyCharm je v resnici neverjetno dober, prav tako pa so izjemna tudi druga orodja tega podjetja. (Vsem, ki bi se radi naučili vročega novega jezika priporočam Kotlin.)
PyCharm nam bo pri programiranju pomagal še veliko bolj kot Visual Studio Code. Znal bo dopolnjevati napol napisana imena (nekaj malega zna tudi VS Code, a PyCharm je veliko zvitejši), pomagal pri tipih spremenljivk, argumentih funkcij, iskanju napak...
Odpremo torej PyCharm in naredimo projekt "Programiranje 1". Na levi strani vidimo nekakšne direktorije. Naredimo poddirektorij z zaporedno številko in naslovom predavanj in v njem novo datoteko z imenom temperature.py. (Kako to naredimo, boste že odkrili sami, saj niste prvič za računalnikom.) Poklikamo novo datoteko in vanjo vnesemo program.
Ko je program vtipkan, pritisnemo Ctrl-Shift-F10 v Windowsih ali Ctrl-Shift-R na Os X ali bogvekaj v Linuxu (ali pa v menuju Run izberemo Run, vendar se raje navadite na bližnjice, saj boste tole letos naredili deset tisočkrat) in PyCharm bo pognal naš program. Vpis in rezultati bodo v spodnjem delu okna.