Funkcije¶
Funkcija print¶
print predstavlja eno od najbolj pogosto uporabljenih funkcij. Vse podane argumente izpiše, mednje da presledek, na koncu pa gre v novo vrstico.
Poglejmo primer:
print('prvi argument', 'drugi', '=', 5.)prvi argument drugi = 5.0
Za bolj splošno uporabo glejmo dokumentacijo:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)kjer so argumenti:
*objectspredstavlja argumente, ki jih želimo izpisati (celovitost zvezdice bo jasna pri obravnavi funkcij, spodaj),seppredstavlja delilni niz (angl. separator),endpredstavlja zaključni niz,filepredstavlja datoteko izpisa (sys.stdoutpredstavlja standard output, v konkretnem primeru to pomeni zaslon oz. ukazna vrstica; pozneje bomo to spremenili),flushv primeruTrueizpis zaključi (sicer lahko zaradi optimizacije ostane v medpolnilniku, angl. buffer).
Pri argumentu end smo zgoraj uporabili t. i. izhodni znak (angl. escape character): \.
Namen izhodnega znaka je, da sledečemu znaku da poseben pomen, nekatere pogoste uporabe so:
\n vstavi prelomi vrstico,
\t vstavi tabulator,
\b izbriše zadnji znak backspace,
\’ izpiše enojni narekovaj ',
\" izpiše dvojni narekovaj ",
\\ prikaže izhodni znak (angl. backslash),
\ na koncu vrstice: niz se nadaljuje v naslednji vrstici (brez znaka za novo vrstico).
Primer (kako ponavadi ne programiramo):
print('pet','et', sep='-', end='=')
print('p:)')pet-et=p:)
In še primer z izhodnimi znaki:
print('Nizi v Pythonu (po PEP8) naj ne bi bili daljši od 79 znakov. \
Razlog je v tem, da nam ni treba pomikati okna levo in desno. \
Da pa vseeno lahko napišemo nize, ki so daljši od 79 znakov \
Uporabimo enojni delilni znak \\ (bodite pozorni na to, \
kako se izpiše: \\)',)Nizi v Pythonu (po PEP8) naj ne bi bili daljši od 80 znakov. Razlog je v tem, da nam ni treba pomikati okna levo in desno. Da pa vseeno lahko napišemo nize, ki so daljši od 80 znakov Uporabimo enojni delilni znak \ (bodite pozorni na to, kako se izpiše: \)
Oblikovanje nizov¶
Pri oblikovanju/formatiranju nizov imamo na voljo več orodij:
f-niz (angl. f-string, f zaradi “formatirani”), dokumentacija,
metoda
.format(), dokumentacija,% oblikovanje, dokumentacija.
Poglejmo si primere:
a = 3.14
print(f'pi = {a}') # f-niz
print('pi = {a}'.format(a = a)) # .format
print('pi = %(a)3.2f' % {'a': a}) # % pi = 3.14
pi = 3.14
pi = 3.14
f-niz je implementiran od Python verzije 3.6 naprej (PEP 498) in predstavlja najbolj enostaven način oblikovanja. Ostala načina navajamo zgolj zato, da se bralec seznani z njimi in da naredimo povezavo na dokumentacijo.
f-niz se vedno začne s f pred prvim narekovajem in omogoča zelo splošno oblikovanje (glejte dokumentacijo).
Vrednost, ki jo želimo znotraj niza oblikovati, damo v zavite oklepaje:
f'besedilo... {ime_arg1:fmt1} ... besedilo...'V zavitih oklepajih je:
pred
:podamo ime vrednosti, ki jo želimo oblikovatiza
:oblikujemo izpis spremenljivke; najpogosteje bomo uporabili fmt oblike:w.df - predstavitev s plavajočo vejico (float)
w.de - predstavitev z eksponentom (exponent)
w.dg - splošni format (general)
ws - niz znakov (string).
w predstavlja (minimalno) skupno širino, d pa število mest za decimalno piko.
Poglejmo si primer:
višina = 1.84
ime = 'Marko'
tekst = f'{ime} je visok {višina} m ali tudi: {višina:e} m, {višina:7.3f} m.'
tekst'Marko je visok 1.84 m ali tudi: 1.840000e+00 m, 1.840 m.'Podobno bi lahko naredili z metodo format in se sklicali na indeks argumenta:
tekst = '{1} je visok {0} m ali tudi: {0:e} m, {0:7.3f} m.'.format(višina, ime)
tekst'Marko je visok 1.84 m ali tudi: 1.840000e+00 m, 1.840 m.'Primer z uporabo slovarja:
parametri = {'visina': 5., 'gostota':100.111, 'ime uporabnika': 'Janko'}f'višina = {parametri["visina"]:7.3f}, gostota = {parametri["gostota"]:7.3e}''višina = 5.000, gostota = 1.001e+02'Oblikovanje s fmt (angl. Format Specification Mini-Language) je izredno bogato. Del za dvopičjem je v splošnem (glejte dokumentacijo):
[[fill]align][sign][#][0][width][grouping_option][.precision][type]kjer so v oglatih oklepajih opcijski parametri (vsi so opcijski):
fillje lahko katerikoli znak,alignoznačuje poravnavo, možnosti:"<"|">"|"="|"^",signoznačuje predznak, možnosti:"+"|"-"|" ",widthdefinira minimalno skupno širino,grouping_optionmožnosti združevanja, možnosti:"_"|","precisiondefinira število števk po decimalnem ločilu,typedefinira, kako naj bodo podatki prikazani, možnosti:"b"|"c"|"d"|"e"|"E"|"f"|"F"|"g"|"G"|"n"|"o"|"s"|"x"|"X"|"%"
Besedili poravnavamo levo z "<", desno z ">" in sredinsko "^". Primer sredinske/desne poravnave (širina 20 znakov):
f'{višina:*^20}' # pred ^ je znak s katerim zapolnimo levo in desno stran'********1.84********'f'{parametri["visina"]:_>20}''_________________5.0'c = 4-2j
f'Kompleksno število {c} je sestavljeno iz realnega ({c.real}) \
in imaginarnega ({c.imag}) dela.''Kompleksno število (4-2j) je sestavljeno iz realnega (4.0)in imaginarnega (-2.0) dela.'Oblikovanje datuma, ure si lahko pogledate v dodatku spodaj.
Delo z datotekami¶
Delo z datotekami je pomembno, saj podatke pogosto shranjujemo v datoteke ali jih beremo iz njih. Datoteko, iz katere želimo brati ali vanjo pisati, moramo najprej odpreti. To izvedemo z ukazom open (dokumentacija):
open(file, mode='r', buffering=-1, encoding=None,
errors=None, newline=None, closefd=True, opener=None)Od vseh argumentov je nujen samo file, ki definira pot do datoteke.
Argument mode je lahko:
'r'za branje (read, privzeto),'w'za pisanje (write, datoteka se najprej pobriše),'x'za ekskluzivno pisanje; če datoteka že obstaja vrne napako,'a'za dodajanje na koncu obstoječe datoteke (append),'b'binarna oblika zapisa,'t'tekstovna oblika zapisa (privzeto),'+'datoteka se odpre za branje in pisanje.
Zadnji trije znaki ('b', 't', '+') se uporabljajo v kombinaciji s prvimi tremi ('r', 'w', 'x'). Primer: mode='r+b' pomeni branje in pisanje binarne datoteke.
Podrobneje bomo spoznali samo branje in pisanje tekstovnih datotek.
Ostali (opcijski) argumenti funkcije open so podrobno opisani v dokumentaciji.
Privzeto je mode='r' (oz. 'rt', ker je privzet tekstovni način), kar pomeni, da se datoteko odpre za branje v tekstovni obliki.
Poglejmo si najprej pisanje v (tekstovno) datoteko (mode='w'):
datoteka = open('data/prikaz vpisa.txt', mode='w')'data/prikaz vpisa.txt' predstavlja relativno pot (glede na mesto, kjer se poganja Jupyter notebook) do datoteke.
Zapišimo prvo vrstico s pomočjo metode write:
datoteka.write('test prve vrstice\n')18Metoda write vrne število zapisanih znakov. Če boste v tem trenutku pogledali vsebino datoteke, je velika možnost, da je še prazna. Razlog je v tem, da je vsebina še v medpolnilniku, ki se izprazni na disk samo občasno ali ob zaprtju datoteke (razlog za tako delovanje je v hitrosti zapisa na disk; za podrobnosti glejte dokumentacijo argumenta buffering funkcije open).
Zapišimo drugo vrstico:
datoteka.write('druga vrstica\n', )14Vpišimo sedaj še nekaj številčnih vrednosti:
for d in range(5):
datoteka.write(f'{d:7.2e}\t {d:9.4e}\n')Datoteko zapremo:
datoteka.close()Sedaj datoteko odpremo za branje in pisanje, mode='r+':
datoteka = open('data/prikaz vpisa.txt', mode='r+')Preverimo vse vrstice s for zanko; v spodnji kodi nam datoteka v vsakem klicu vrne eno vrstico:
for line in datoteka:
print(line, end='')test prve vrstice
druga vrstica
0.00e+00 0.0000e+00
1.00e+00 1.0000e+00
2.00e+00 2.0000e+00
3.00e+00 3.0000e+00
4.00e+00 4.0000e+00
Pri uvodu v funkcijo print smo omenili argument file, ki definira datoteko, v katero se piše (privzet je standardni izhod oz. zaslon). Če kot argument file posredujemo datoteko, ki je odprta za pisanje:
print('konec', file=datoteka)
datoteka.close()se vsebina zapiše v datoteko. Rezultat lahko preverite v datoteki!
Tukaj je lepa priložnost, da spoznamo stavek with (dokumentacija). Celovitost stavka with presega namen tega predmeta, je pa zelo preprosta uporaba pri delu z datotekami, zato si poglejmo primer:
with open('data/prikaz vpisa.txt') as datoteka:
for line in datoteka:
print(line, end='')test prve vrstice
druga vrstica
0.00e+00 0.0000e+00
1.00e+00 1.0000e+00
2.00e+00 2.0000e+00
3.00e+00 3.0000e+00
4.00e+00 4.0000e+00
konec
Stavek with rezultat funkcije open shrani v (as) ime datoteka, potem pa za vsako vrstico izpišemo vrednosti. Pri izhodu iz stavka with se samodejno pokliče metoda datoteka.close(). Stavek with nam torej omogoča pisanje pregledne in kompaktne kode.
Funkcije v splošnem¶
V Pythonu je veliko funkcij že vgrajenih (glejte dokumentacijo); funkcije pa lahko tudi napišemo sami ali jih uvozimo iz t. i. modulov (spodaj bomo uvozili datetime, več si bomo pogledali pozneje).
Generični primer funkcije je (dokumentacija):
def ime_funkcije(parametri):
'''docstring'''
[koda]
return vsebinaPri tem izpostavimo:
defoznačuje definicijo funkcije,ime_funkcijeimena funkcije po PEP8 pišemo z malo, večbesedna povežemo s podčrtajem,parametriparametri funkcije, več bomo povedali spodaj,docstring(opcijsko) dokumentacija funkcije,[koda]koda funkcije,return(opcijsko) ukaz za izhod iz funkcije, kar sledi se vrne kot rezultat (če nireturnali po return ni ničesar, se vrneNone)
Primer preproste funkcije:
def površina(dolžina, širina):
S = dolžina * širina
return Spovršina(1, 20)20Posredovanje argumentov v funkcije¶
Python pozna dva načina posredovanja argumentov:
glede na mesto (positional)
glede na ime.
Poglejmo si oba načina na primeru:
površina(3, 6) # pozicijsko18površina(širina = 3, dolžina = 6) # glede na ime18Priporočeno je, da argumente posredujemo z imenom; s tem zmanjšamo možnost napake!
Če ne podamo imena, potem se privzame ime glede na vrstni red argumentov; primer:
površina(3, širina=4)12V kolikor mešamo pozicijsko in poimensko posredovanje argumentov, morajo najprej biti navedeni pozicijski argumenti, šele nato poimenski. Pri tem poimenski ne sme ponovno definirati pozicijskega; ker je dolžina prvi argument, bi klicanje take kode:
površina(3, dolžina=4)povzročilo napako.
Primer dobre prakse pri definiranju argumentov¶
Pogosto funkcije dopolnjujemo in dodajamo nove argumente ali pa število argumentov funkciji sploh ne moremo vnaprej definirati!
Python s tem nima težav. Argumente, ki niso eksplicitno definirani obvladamo z:
*[ime0]terka[ime0]vsebuje vse pozicijske argumente, ki niso eksplicitno definirani,**[ime1]slovar[ime1]vsebuje vse poimenske argumente, ki niso eksplicitno definirani.
Poglejmo primer:
def neka_funkcija(student, izpit = True):
''' Prva verzija funkcije'''
print(f'Študent {student} se je prijavil na izpit: {izpit}.')neka_funkcija('Janez', izpit=True)Študent Janez se je prijavil na izpit: True.
Sedaj pa pripravimo drugo, nadgrajeno, verzijo (omogoča enako uporabo kot prva verzija):
def neka_funkcija(*terka, **slovar):
''' Druga verzija funkcije '''
student = terka[0]
izpit = slovar.get('izpit', True) # True je privzeta vrednost
izpisi_sliko = slovar.get('izpisi_sliko', False) # False je privzeta vrednost
print(f'Študent {student} se je prijavil na izpit: {izpit}.')
if izpisi_sliko:
print('slika:)')neka_funkcija('Janez', izpit=True)Študent Janez se je prijavil na izpit: True.
neka_funkcija('Janez', izpit=True, izpisi_sliko=True, neobstoječi_argument='ni')Študent Janez se je prijavil na izpit: True.
slika:)
Posredovanje funkcij kot argument¶
Tukaj bi želeli izpostaviti, da so argumenti lahko tudi druge funkcije.
Poglejmo si primer:
def oblika_a(vrednost):
return f'Prikaz vrednosti: {vrednost}'
def oblika_b(vrednost):
return f'Prikaz vrednosti: {vrednost:3.2f}'
def izpis(oblika, vrednost):
print(oblika(vrednost))Imamo torej dve funkciji oblika_a in oblika_b, ki malenkost drugače oblikujeta numerično vrednost.
Poglejmo uporabo:
izpis(oblika_a, 3)Prikaz vrednosti: 3
izpis(oblika_b, 3)Prikaz vrednosti: 3.00
Docstring funkcije¶
docstring je neobvezen del definicije funkcije, ki dokumentira funkcijo in njeno uporabo. Iz tega stališča je zelo priporočeno, da ga uporabimo.
Dokumentacija za docstring navaja bistvene elemente:
prva vrstica naj bo kratek povzetek funkcije,
če je vrstic več, naj bo druga prazna (da se vizualno loči prvo vrstico od preostalega teksta),
uporabimo tri narekovaje (dvojne " ali enojne '), ki označujejo večvrstični niz črk.
Primer dokumentirane funkcije:
def površina(dolžina = 1, širina = 10):
""" Izračun površine pravokotnika
Funkcija vrne vrednost površine.
Argumenti:
dolžina: dolžina pravokotnika
širina: širina pravokotnika
"""
return dolžina * širinaPrimer klica s privzetimi argumenti (med klicem funkcije lahko s pritiskom [shift]+[tab] dostopamo do pomoči):
površina()10Lokalna/globalna imena¶
Preprosto vodilo pri funkcijah je: funkcija vidi ven, drugi pa ne vidijo noter. Funkcija ima notranja imena, ki se ne prekrivajo z istimi imeni v drugih funkcijah.
Poglejmo si primer:
zunanja = 3
def prva():
notranja = 5
print(f'Tole je zunanja vrednost: {zunanja}, tole pa notranja: {notranja}')prva()Tole je zunanja vrednost: 3, tole pa notranja: 5
Ker ime notranja zunaj funkcije prva ni definirano, bi klicanje:
notranjazunaj funkcije vrnilo napako (v funkcijo ne vidimo).
Tukaj velja omeniti, da je posredovanje zunanjih imen v funkcijo mimo argumentov funkcije odsvetovano.
return¶
Ukaz return vrne vrednosti iz funkcije. Doslej smo spoznali rezultate v obliki ene spremenljivke; ta spremenljivka pa je lahko tudi terka.
Poglejmo si primer:
def vrnem_terko():
return 1, 2, 3 # to je ekvivalenten zapis za terko: (1, 2, 3)vrnem_terko()(1, 2, 3)Rezultat funkcije lahko ujamemo tako:
rezultat = vrnem_terko()
rezultat(1, 2, 3)Ali tako, da vrednosti razpakiramo (to sicer velja v splošnem za terke):
i1, i2, i3 = vrnem_terko()
i1 # izpis samo ene vrednosti1Anonimna funkcija/izraz¶
Anonimna funkcija (glejte dokumentacijo) je funkcija, kateri ne damo imena (zato je anonimna), ampak jo definiramo z ukazom lambda. Tipična uporaba je:
lambda [seznam parametrov]: izrazlambda funkcijo si bomo pogledali na primeru razvrščanja:
seznam = [-4, 3, -8, 6]od najmanjše do največje vrednosti. To lahko izvedemo z vgrajeno metodo sort (dokumentacija):
sort(*, key=None, reverse=False)Metoda ima dva opcijska argumenta:
keyključ, po katerem razvrstimo elementereverse, če jeFalse, se med vrednostmi ključa uporabi<sicer>.
Opomba: list.sort() izvede razvrščanje na obstoječem seznamu in ne vrne seznama. Funkcija sorted() (glejte dokumentacijo) pa vrne seznam urejenih vrednosti.
Poglejmo primer:
seznam = [-4, 3, -8, 6]
seznam.sort()
seznam[-8, -4, 3, 6]Sedaj uporabimo ključ, kjer se bo za primerjavo vrednosti razvrščanja uporabila kvadratna vrednost:
seznam.sort(key = lambda a: a**2)
seznam[3, -4, 6, -8]Obravnavanje izjem¶
Pri programiranju se relativno pogosto pojavijo izjeme; na primer: deljenje z nič.
1/0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-50-05c9758a9c21> in <module>()
----> 1 1/0
ZeroDivisionError: division by zeroV primeru izjeme Python opozori na to in prekine izvajanje. Ni dobro, da se program prekine ali zruši; iz tega razloga bi zgornjo situacijo programer začetnik verjetno reševal s stavkom if. Takšen pristop pa ni preveč uporaben niti splošen in zato je v večini modernih programskih jezikih uveljavljeno obravnavanje izjem.
Pogledali si bomo nekatere osnove, ki bodo študentom predvsem olajšale branje in razumevanje kod drugih avtorjev.
Izjeme obvladujemo s stavkom try:
try:
[koda0]
except:
[koda1]
finally:
[koda2]V stavki try se except izvede, če se v kodi [koda0] pojavi izjema, finally je opcijski in se izvede v vsakem primeru ob izhodu iz stavka try.
Poglejmo primer, ko enostavno nadaljujemo z izvajanjem:
try:
1/0
except:
passUkaz pass uporabimo, ko sintaksa zahteva stavek (kodo) za izvajanje, vendar ne želimo nobenega ukrepa (glejte dokumentacijo).
S pomočjo except lahko lovimo tudi različne izjeme, to naredimo tako:
try:
1/0
except ZeroDivisionError:
print('Deljenje z ničlo!') # ali kakšna druga akcija
except:
print('Nepričakovana napaka.') # odsvetovano; dobro je predvideti napako!Deljenje z ničlo!
Sedaj uporabimo isto kodo za primer deljenja števila z nizom:
try:
1/'to pa ne gre'
except ZeroDivisionError:
print('Deljenje z ničlo!') # ali kakšna druga akcija
except:
print('Nepričakovana napaka.') # odsvetovano; dobro je predvideti napako!Nepričakovana napaka.
Proženje izjem¶
Izjeme pa lahko tudi sami prožimo; to naredimo z ukazom raise (dokumentacija).
Primer proženja napake je:
raise Exception('Opis izjeme')preprost, vendar celovit, primer, ko bi pričakovali, da je ime_osebe tipa str:
ime_osebe = 1
try:
if type(ime_osebe) != str:
raise Exception(f'Ime ni pričakovanega tipa `str`.')
except Exception as izjema:
print(izjema)Ime ni pričakovanega tipa `str`.
Osnove modulov¶
Z moduli lahko na enostaven način uporabimo že napisano kodo. Preprosto povedano, moduli nam v Pythonu omogočajo relativno enostavno ohranjanje preglednosti in reda. Ponavadi v modul zapakiramo neko zaključeno funkcijo, skupino funkcij ali npr. objekt (pozneje bomo spoznali, kaj je objekt).
Za podroben opis uvažanja modulov glejte dokumentacijo.
V mapi moduli se nahaja datoteka prvi_modul.py, ki ima sledečo vsebino:
def kvadrat(x=1):
return x**2Pomembno: pogosto module hierarhično razporejamo po direktorijih; direktorij z moduli imenujemo paket (angl. package). Če direktorij vsebuje datoteko (lahko tudi prazno) __init__.py, gre za običajni paket; od Pythona 3.3 naprej pa se direktorij obnaša kot paket tudi brez nje (t. i. namespace package). V zgornjem primeru se tako mapa moduli obnaša kot paket, v njem pa je modul prvi_modul (datoteka prvi_modul.py).
Module tipično uvažamo na dva načina:
Prvi način:
from moduli import prvi_modulv tem primeru uvozimo imenski prostor prvi_modul; to pomeni, da funkcijo kvadrat() kličemo tako: prvi_modul.kvadrat().
Drugi način uvažanja modula:
import moduli.prvi_modulUvozimo imenski prostor moduli.prvi_modul; to pomeni, da funkcijo kvadrat() kličemo tako: moduli.prvi_modul.kvadrat(). (Sam ukaz import moduli podmodulov ne uvozi samodejno.)
V kolikor želimo uvoziti funkcije v modulu prvi_modul, to naredimo tako:
from moduli import prvi_modulSedaj lahko funkcijo kvadrat kličemo tako:
prvi_modul.kvadrat(5)25Z ukazom from lahko uvozimo samo del modula. Primer:
from moduli.prvi_modul import kvadratSedaj kličemo neposredno funkcijo kvadrat:
kvadrat(6)36Funkcije ali module lahko tudi preimenujemo. Primer:
from moduli.prvi_modul import kvadrat as sqr
sqr(7)49Kje Python išče module?
V trenutni mapi (to je tista, v kateri ste prožili
jupyter notebook),v mapah, definiranih v
PYTHONPATH,v mapah, kjer je nameščen Python (poddirektorij
site-packages).
Uvoz modulov in Jupyter notebook¶
V tej knjigi bomo, zaradi pedagoških razlogov, module vedno uvažali takrat, ko jih bomo prvič potrebovali. Pravila dobre prakse in pregledne kode priporočajo, da se uvoze vseh modulov izvede na vrhu Jupyter notebooka!
Modul pickle¶
Modul pickle bomo velikokrat uporabljali za zelo hitro in kompaktno shranjevanje in branje podatkov.
pickle vrednosti spremenljivke shrani v taki obliki, kot so zapisane v spominu. V primeru realnih števil tako ne izgublja na natančnosti (zapis v tekstovno obliko izgublja natančnost, saj definiramo število izpisanih števk, ki pa je lahko manjše od števila decimalnih mest v spominu). Poleg tega pa je zapis v spominu ponavadi manj zahteven kakor zapis v tekstovni obliki. Ker vrednosti ni treba pretvarjati v/iz tekstovno/e obliko/e, je pisanje/branje tudi zelo hitro! Tukaj si bomo pogledali osnovno uporabo, celovito je pickle opisan v dokumentaciji.
pickle ima dve pomembni metodi:
dump(obj, file, protocol=None, *, fix_imports=True)za shranjevanje objektaobj,load(file, *, fix_imports=True, encoding="ASCII", errors="strict")za branje datotekefile.
Uporabo si bomo pogledali na primeru. Najprej uvozimo modul:
import pickleZapišimo vrednosti slovarja a v datoteko data/stanje1.pkl:
a = {'število': 1, 'velikost': 10}
with open('data/stanje1.pkl', 'wb') as datoteka:
pickle.dump(a, datoteka, protocol=-1) # pazite: uporabite protocol=-1, da boste uporabili zadnjo verzijoOpazimo, da so datoteko odprli za pisanje v binarni obliki wb. Pomembno je tudi, da uporabimo zadnjo verzijo protokola (parameter protocol); privzeta je izbrana zaradi združljivosti s starejšimi različicami Pythona, zadnja pa je praviloma najhitrejša.
Sedaj vrednosti preberimo nazaj v b in ga prikažemo:
with open('data/stanje1.pkl', 'rb') as datoteka:
b = pickle.load(datoteka)
b{'število': 1, 'velikost': 10}Zgoraj smo trdili, da je pristop zelo hiter; preverimo to.
Najprej pripravimo podatke (seznam 50000 vrednosti tipa int):
data = list(range(50000))Pisanje v tekstovni obliki
%%timeit
datoteka = open('data/data.txt', mode='w')
for d in data:
datoteka.write(f'{d:7.2e}\n' )
datoteka.close()165 ms ± 13.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Pisanje s pomočjo pickle:
%%timeit
with open('data/data.pkl', 'wb') as datoteka:
pickle.dump(data, datoteka, protocol=-1) 3.21 ms ± 319 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Pohitritev je več desetkratna!
Uporaba modulov iz spleta¶
Poleg vgrajenih modulov in tistih, ki jih pripravimo sami, obstaja še velika množica modulov, ki jih lahko najdemo na spletu in Pythonu dodajajo nove funkcionalnosti. Šele ti moduli naredijo ekosistem Pythona tako uporaben.
Modul je tehnično gledano ena datoteka, kadar nek večji modul vsebuje več modulov, pa lahko začnemo govoriti o paketih. Najbolj pomembne pakete na področju inženirskih ved bomo spoznali v okviru te knjige.
Module oz. pakete lahko posodabljamo ali nameščamo nove, pri tem nam pomagajo t. i. upravljalniki paketov (angl. package manager). Najbolj pogost upravljalnik paketov je pip (dokumentacija).
Upravljalnik paketov pip¶
pip je upravljalnik paketov z dolgo zgodovino in podpira veliko število paketov (pypi.org).
Že nameščene pakete najdemo z ukazom v ukazni vrstici (dokumentacija):
pip listNamesto izhoda v ukazno vrstico bomo večkrat uporabljali možnost Jupyter notebooka, ko s pomočjo klicaja (!) v celici s kodo izvedemo ukaz v ukazni vrstici (gre za kratko obliko magičnega ukaza %sx - shell execute, glejte dokumentacijo). Opomba: dva klicaja bi vrnila celoten rezultat neposredno v notebook (ker je izpis zelo dolg, smo se temu izognili).
Poglejmo primer:
rezultat = !pip list
rezultat[:5]['Package Version',
'--------------------------------- ------------',
'accessible-pygments 0.0.4',
'alabaster 0.7.13',
'anyio 4.2.0']Pakete namestimo z ukazom (v ukazni vrstici):
pip install [ime_paketa]posodobimo z:
pip install [ime_paketa] --upgradein odstranimo z:
pip uninstall [ime_paketa]Za več glejte dokumentacijo.
Primer namestitve paketa¶
Sicer pa pakete najpogosteje najdemo na spletu (pypi.org). Pojdite na omenjeni portal in poiščite pakete na temo snemanja posnetkov iz portala www.youtube.com. Z iskanjem “pytube” najdemo obetaven paket, ki ga namestimo:
Sedaj modul uporabimo (za podrobnosti uporabe glejte dokumentacijo). Najprej uvozimo celotni paket:
import pytube
yt = pytube.YouTube('https://www.youtube.com/watch?v=P4IrAXbpeyI') # kreiramo instanco objekta (kaj to točno pomeni, spoznamo pozneje)
yt.streams.get_highest_resolution().download() #Prenesemo video'c:\\_j\\Work Janko\\Pedagosko delo\\_predavanja\\Programiranje in numericne metode\\pynm\\notebooks\\Strojništvo je zabavno - 2 del.mp4'Dodatno¶
Oblikovanje datuma in časa¶
Najprej uvozimo modul za delo z datumom in časom datetime in prikažemo trenutni čas z datumom (uporabimo funkcijo now()):
import datetime
sedaj = datetime.datetime.now()
sedajdatetime.datetime(2024, 1, 4, 14, 35, 58, 68563)Podatek o času oblikujemo:
f'{sedaj:%Y-%m-%d %H:%M:%S}''2024-01-04 14:35:58'Oblikovanje datuma in ure sledi metodam:
strftime(dokumentacija) se uporablja za pretvorbo izdatetimev niz črk,strptime(dokumentacija) se uporablja za pretvorbo iz niza črk v tipdatetime.
Kako izpisati ustrezno obliko (torej kako uporabiti znake %Y, %m itd.) je prav tako podrobno pojasnjeno v dokumentaciji.
Poglejmo si primer pretvorbe tipa datetime v niz (glede na zgoraj smo dodali še %a, da se izpiše ime dneva):
sedaj.strftime('%Y-%m-%d %H:%M:%S %a')'2024-01-04 14:35:58 Thu'Sedaj v obratno smer, torej iz niza v datetime:
datetime.datetime.strptime('2017-09-28 05:31:45', '%Y-%m-%d %H:%M:%S')datetime.datetime(2017, 9, 28, 5, 31, 45)Nekateri moduli¶
openpyxlza pisanje in branje Excel xlsx/xlsm datotek: vir,
Regularni izrazi (zelo močno orodje za iskanje po nizih): vir.
Modul sys¶
Python ima veliko število vgrajenih modulov (in še veliko se jih lahko prenese s spleta, npr. tukaj), ki dodajo različne funkcionalnosti.
Modul sys omogoča dostop do objektov, ki jih uporablja interpreter.
Poglejmo si primer; najprej uvozimo modul:
import sysMape, kjer se iščejo moduli, lahko preverimo z ukazom sys.path (dokumentacija):
sys.path['c:\\_j\\Work Janko\\Pedagosko delo\\_predavanja\\Programiranje in numericne metode\\pynm\\notebooks',
'C:\\Users\\janko\\AppData\\Local\\Programs\\Python\\Python311\\python311.zip',
'C:\\Users\\janko\\AppData\\Local\\Programs\\Python\\Python311\\DLLs',
'C:\\Users\\janko\\AppData\\Local\\Programs\\Python\\Python311\\Lib',
'C:\\Users\\janko\\AppData\\Local\\Programs\\Python\\Python311',
'',
'C:\\Users\\janko\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages',
'C:\\Users\\janko\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\win32',
'C:\\Users\\janko\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\win32\\lib',
'C:\\Users\\janko\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\Pythonwin']Modul os¶
Modul os je namenjen delu z operacijskim sistemom in skrbi za združljivost z različnimi operacijskimi sistemi (če npr. napišete program na sistemu Windows, bo delal tudi na sistemu linux).
Uvozimo modul:
import osPogljemo trenutno mapo:
os.path.curdir'.'ali trenutno mapo v absolutni obliki:
os.path.abspath(os.path.curdir)'c:\\_j\\Work Janko\\Pedagosko delo\\_predavanja\\Programiranje in numericne metode\\pynm\\notebooks'Kako najdemo vse datoteke in mape v direktoriju?
seznam = os.listdir()Prikažimo prve štiri s končnico ipynb:
i = 0
for ime in seznam:
if os.path.isfile(ime):
if ime[-5:] == 'ipynb':
print(f'Našel sem datoteko: {ime:s}')
i +=1
if i>3:
breakNašel sem datoteko: Predavanje 01 - Uvod v Python.ipynb
Našel sem datoteko: Predavanje 02 - Print, delo z datotekami, funkcije, moduli.ipynb
Našel sem datoteko: Predavanje 03 - Moduli, numpy, matplotlib.ipynb
Našel sem datoteko: Predavanje 04 - Objektno programiranje, simbolno računanje.ipynb
Za več glejte dokumentacijo.
Funkcija print, formatiranje nizov¶
Vprašanje 1: V poljubno poimenovan niz zapišite svoje ime in priimek. Z uporabo funkcije print in f-nizov izpišite poljuben tekst, v katerega vključite tudi pripravljen niz.
Vprašanje 2: Z vsa naravna števila od 1 do 10 v for zanki izpišite '10 / <število> = <rezultat deljenja>'. Uporabite funkijo print in f-nize! Prikažite različne možnosti formatiranja.
Vprašanje 3: Z uporabo funkcije print in f-nizov podatke iz slovarja zapišite v tabelarični obliki, '<ključ> \t <vrednost>' (namig: slovar.items()).
podatki = {'a': 0, 'F': 1013, 'k': 0.19, 'H': 55, 'l': 19.22, 'n': 7, 'v': 77.6}Funkcije¶
Vprašanje 4: Definirajte funkcijo, ki sprejme več nepoimenovanih argumentov in vrne njihovo vsoto.
Vprašanje 5: Definirajte funkcijo, ki sprejme več poimenovanih argumentov. Če ji kot argumenta posredujete maso m in hitrost v, naj vrne kinetično energijo, .
Delo z datotekami¶
Vprašanje 6: Po vzoru ene od zgornjih nalog podatke iz slovarja v tabelarini obliki zapišite v tekstovno datoteko.
pot_do_datoteke = './data/tabela.txt'
podatkiVprašanje 7: Preberite prej zapisano tekstovno datoteko, vse vrstice shranite seznam.
pot_do_datotekeVprašanje 8: Definirajte funkcijo preberi_vrstice, ki prebere poljubno tekstovno datoteko in vrne seznam vseh njenih vrstic. Njen argument naj bo pot do datoteke.
Izpeljevanje seznamov, terk, slovarjev...¶
Vprašanje 9: Številčne vrednosti podatkov, ki so v zgornjem seznamu zapisane v obliki nizov, pretvorite v števila s plavajočo vejico. Uporabite izpeljevanje seznamov.
Kontrola napak in izjem¶
Vprašanje 10: Za vse vrednosti i v range(-10,10) v seznam zapišite rezultat 10 / i. Uporabite izpeljevanje seznamov. Lovite in izpisujte izjeme.
Vprašanje 11 Funkcijo preberi_vrstice iz ene od prejšnjih nalog, ki prebere tekstovno datoteko in vrne seznam vseh njenih vrstic, nadgradite tako, da bo v primeru neustrezno podane poti ulovila in izpisala napako.
Moduli¶
Vprašanje 12: Funkcijo iz prejšnje naloge shranite v mapo moj_modul, v modul moja_funkcija.py. Modul uvozite in funkcijo uporabite.
from moj_modul.moja_funkcija import preberi_vrstice as pv_iz_modula