Tečajna lista
Testi
V isti direktorij odzipaj vse datoteke iz testi-tecajna-lista.zip. Poleg običajnih testov boš dobil še tri datoteke. V tecajnica.txt je tečajnica, kakršno dobimo na NLB.
Obvezna naloga
Napiši funkcijo preberi(ime_dat)
, ki prebere tečajnico v slovar, katerega ključi so valute, vrednosti pa terke s prodajnim in nakupnim tečajem te valute. Če ji podamo kot argument "tecajnica2.txt"
, vrne {'GBP': (0.8639, 0.8399), 'USD': (1.0748, 1.0508)}
.
Napiši funkcijo izpisi(tecajnica, valute)
, ki (ime je zavajajoče!) vrne niz z lepo oblikovanim "izpisom" podanih valut. Niz mora oblikovan natančno tako, kot zahteva naloga. Če pokličemo `izpisi(tecajnica, ["GBP", "USD", "RUB", "HRK", "HUF"]), mora vrniti niz
GBP......0.8639......0.8399
USD......1.0748......1.0508
RUB.....71.9393.....66.5393
HRK......7.6508......7.4208
HUF....315.8900....307.0900
Napiši funkcijo zapisi(ime_dat, tecajnica)
, ki ustvari datoteko s podanim imenom (ime_dat
) in vanjo zapiše tečajnico v enaki obliki, kot je gornja, za vse valute v podani tecajnica
in to v abecednem vrstnem redu.
Datoteka, ki jo izpiše, mora biti točno taka kot datoteka "pravilna.txt". Pazi, da je ne spremeniš: testi v resnici preverjajo, ali je datoteka, ki si jo sestavil, enaka datoteki "pravilna.txt".
Navodilo za delo: znajdi se. Naloge se lahko lotiš z običajnimi metodami nizov (split
in podobne), lahko pa uporabiš kakšno knjižnico, ki jo dobimo s Pythonom. Dodatne knjižnice pa so prepovedane (iz preprostega razloga: ne bomo jih nameščali samo za to, da bi testirali vaš program ;).
Rešitev
Branje: odpremo datoteko ter preberemo in vržemo stran prvo vrstico (f.readline()
). Nato gremo z zanko for
čez datoteko (for vrstica in f
). Zdaj pa bomo hitro opravili: v vrstici zamenjamo vejice s pikami, jo razbijemo na kose in vzamemo le zadnje tri, torej vrstica.replace(",", ".").split()[-3:]
. Kar dobimo, shranimo kot ime, nakupni, prodajni
. V slovar tecajnica
pod ključ ime zapišemo terko z vrednostjo nakupni
in prodajni
, ki ju mimogrede pretvorimo v float
.
def preberi(ime_dat):
f = open(ime_dat)
f.readline()
tecajnica = {}
for vrstica in f:
ime, nakupni, prodajni = vrstica.replace(",", ".").split()[-3:]
tecajnica[ime] = float(nakupni), float(prodajni)
return tecajnica
Izpis: naredimo prazen niz. Sprehodimo se čez vse valute, ki jih je potrebno izpisati. Iz slovarja vzamemo nakupni in prodajni tečaj ter to dodamo primerno oblikovano v niz. Primerna oblika je takšna, da vzamemo najprej ime, nato pa oba tečaja, ki ju poravnamo s piko, na 12 mest, od tega 4 decimalke (:.>12.4f
).
def izpisi(tecajnica, valute):
s = ""
for valuta in valute:
nakupni, prodajni = tecajnica[valuta]
s += "{}{:.>12.4f}{:.>12.4f}\n".format(valuta, nakupni, prodajni)
return s
Zapis v datoteko: odpremo datoteko in vanjo zapišemo, kar vrne gornja funkcija, pri čemer zahtevamo, da izpiše vse valute, sortirane po abecedi.
def zapisi(ime_dat, tecajnica):
open(ime_dat, "w").write(izpisi(tecajnica, sorted(tecajnica)))
Dodatna naloga
Bolj uraden vir tečajev je Banka Slovenije. Ta objavlja tečajno listo na strani http://www.bsi.si/_data/tecajnice/dtecbs.xml. Če to stran odprete v brskalniku, jo bo pokazal lepšo, kot je v resnici. V resnici pa je vse to besedilo nabasano v eno samo vrstico, brez presledkov.
Tvoja naloga tokrat ni prebrati datoteko, temveč prebrati to spletno stran in jo zložiti v podoben slovar, kot zgoraj, le da bo pri vsaki valuti navedena le ena vrednost.
Malo pomoči: vsebino spletne strani lahko prebereš z
import urllib.request
xml = urllib.request.urlopen("http://www.bsi.si/_data/tecajnice/dtecbs.xml").read().decode("ascii")
Po tem bo xml
niz z vsebino strani. Najboljše, da si ga izpišeš s print
, da boš videl(a), kako grd je.
Rešitev
Tole je kar zoprno. Vse skupaj dobimo kot en niz. "Posplitamo" ga po oznaka="
, da ga razbijemo na valute. V delčkih, ki jih dobimo, bodo prvi trije znaki vedno ime valute, tisto kar je med prvim znakom >
in prvim <
pa bo vrednost. Ni težko, je pa grdo.
def preberi_bs():
import urllib.request
xml = urllib.request.urlopen("http://www.bsi.si/_data/tecajnice/dtecbs.xml").read().decode("ascii")
vrstice = xml.split('oznaka="')[1:]
tecajnica = {}
for vrstica in vrstice:
valuta = vrstica[:3]
vrstica = vrstica[vrstica.index(">")+ 1:vrstica.index("<")]
tecajnica[valuta] = float(vrstica)
return tecajnica
Predvsem pa se to ne dela tako. Ta oblika zapisa, xml, služi prav temu, da bi ga bilo lahko brati s programom. In v resnici ga je, le pravi modul potrebujemo. (Za domačo nalogo seveda nisem pričakoval takšne rešitve. Če je kdo rešil na ta, pravi način, pa ni seveda nič narobe.)
def preberi_bs():
import urllib.request
from xml.dom import minidom
bs = minidom.parse(urllib.request.urlopen("http://www.bsi.si/_data/tecajnice/dtecbs.xml"))
return {tecaj.getAttribute("oznaka"): float(tecaj.childNodes[0].nodeValue)
for tecaj in bs.getElementsByTagName("tecaj")}