Naloge
Vreme
Napišite funkcijo preberi_vrstice(ime_datoteke)
, ki prebere in vrne seznam vrstic v datoteki ime_datoteke
.
Primer za datoteko podatki.txt:
>>> preberi_vrstice('podatki.txt')
['Ljubljana;oblačno;12.1', 'Maribor;sončno;9', 'Koper;sončno;14.7']
Rešitev
Z zanko fordef preberi_vrstice(ime_datoteke):
f = open(ime_datoteke, "r", encoding="utf-8")
lines = []
for line in f:
lines.append(line.strip())
f.close()
return lines
ali z metodama read in splitlines
def preberi_vrstice(ime_datoteke):
return open(ime_datoteke, "r", encoding="utf-8").read().splitlines()
Napiši funkcijo preberi_csv(ime_datoteke)
, ki odpre in prebere datoteko ime_datoteke
, ki v vsaki vrstici vsebuje s podpičji ločene vremenske podatke (kraj, vreme in temperaturo), ter jih vrne kot seznam terk.
>>> podatki = preberi_csv('podatki.txt')
>>> podatki
[('Ljubljana', 'oblačno', 12.1), ('Maribor', 'sončno', 9.0), ('Koper', 'sončno', 14.7)]
Rešitev
def preberi_csv(fname):
sez = []
for vrstica in preberi_vrstice(fname):
kraj, vreme, temp = vrstica.split(';')
sez.append((kraj, vreme, float(temp)))
return sez
Napiši funkcijo oblikuj(podatki)
, ki sprejme seznam terk podatki
z vremenskimi podatki in vrne seznam nizov, ki so oblikovani, kot je prikazano spodaj:
>>> oblikuj(podatki)
['Kraj: Ljubljana, Vreme: oblačno, Temperatura: 12.1°C',
'Kraj: Maribor, Vreme: sončno, Temperatura: 9.0°C',
'Kraj: Koper, Vreme: sončno, Temperatura: 14.7°C']
Rešitev
def oblikuj(podatki):
sez = []
for kraj, vreme, temp in podatki:
sez.append(f'Kraj: {kraj}, Vreme: {vreme}, Temperatura: {temp}°C')
return sez
Izpis iz prejšnje naloge se nam ni najbolj posrečil, zato se odločimo, da bomo podatke zapisali v tabeli. V ta namen napiši funkcijo oblikuj_tabelo(podatki)
, ki vrne seznam nizov, ki so oblikovani na prikazan način.
>>> oblikuj_tabelo(podatki)
['Kraj Vreme Temperatura (°C)',
'------------------------------------------------',
'Ljubljana oblačno 12.1',
'Maribor sončno 9.0',
'Koper sončno 14.7']
Rešitev
def oblikuj_tabelo(podatki):
sez = ['Kraj Vreme Temperatura (°C)',
'------------------------------------------------']
for kraj, vreme, temp in podatki:
sez.append(f'{kraj:16}{vreme:16}{temp:16}')
return sez
Napiši funkcijo oblikuj_tabelo_f(podatki)
tako, da se bo temperatura izpisala v Fahrenheitovi lestvici. Rezultat zaokroži na eno decimalno mesto.
>>> oblikuj_tabelo_f(podatki)
['Kraj Vreme Temperatura (°F)',
'------------------------------------------------',
'Ljubljana oblačno 53.8',
'Maribor sončno 48.2',
'Koper sončno 58.5']
Rešitev
def oblikuj_tabelo_f(podatki):
sez = ['Kraj Vreme Temperatura (°F)',
'------------------------------------------------']
for kraj, vreme, temp in podatki:
temp_f = temp * 9 / 5 + 32
sez.append(f'{kraj:16}{vreme:16}{temp_f:16.1f}')
return sez
Izpis bi lahko bil še preglednejši, če bi tabelo oblikovali, kot je prikazano spodaj
(dokumentacija). V ta namen napiši funkcijo oblikuj_pike(podatki)
.
>>> oblikuj_pike(podatki)
['Kraj Vreme Temperatura (°F)',
'------------------------------------------------',
'Ljubljana.......oblačno.....................53.8',
'Maribor.........sončno......................48.2',
'Koper...........sončno......................58.5']
Rešitev
def oblikuj_pike(podatki):
sez = ['Kraj Vreme Temperatura (°F)',
'------------------------------------------------']
for kraj, vreme, temp in podatki:
temp_f = temp * 9 / 5 + 32
sez.append(f'{kraj:.<16}{vreme:.<16}{temp_f:.>16.1f}')
return sez
V zadnjem stolpcu izpiši temperaturo v Fahrenheitih in Celzijah s funkcijo oblikuj_fc(podatki)
>>> oblikuj_fc(podatki)
['Kraj Vreme Temperatura °F (°C)',
'------------------------------------------------',
'Ljubljana.......oblačno..............53.8 (12.1)',
'Maribor.........sončno................48.2 (9.0)',
'Koper...........sončno...............58.5 (14.7)']
Rešitev
def oblikuj_fc(podatki):
sez = ['Kraj Vreme Temperatura °F (°C)',
'------------------------------------------------']
for kraj, vreme, temp in podatki:
temp_f = temp * 9 / 5 + 32
temp_fc = f'{temp_f:.1f} ({temp:.1f})'
sez.append(f'{kraj:.<16}{vreme:.<16}{temp_fc:.>16}')
return sez
Napiši funkcijo shrani(vrstice, ime_datoteke)
, ki seznam nizov vrstice
shrani vsakega v svojo vrstico v datoteko ime_datoteke
.
>>> shrani(['prva vrstica', 'druga vrstica', 'tretja vrstica'], 'datoteka.txt')
Rešitev
def shrani(vrstice, ime_datoteke):
f = open(ime_datoteke, "w")
for vrstica in vrstice:
f.write(vrstica + '\n')
f.close()
Najdaljše besede
Napiši funkcijo najdaljse_besede(s)
, ki v nizu s
poišče vse
najdaljše besede in jih vrne, ločene z vejico.
>>> najdaljse_besede('ob znaku bo ura deset in pet minut')
'znaku, deset, minut'
Rešitev
def najdaljse_besede(s):
xs = s.split()
# Poišči dolžino najdaljše besede
naj = 0
for word in xs:
if len(word) > naj:
naj = len(word)
# Poišči besede dolžine `naj`
ys = []
for word in xs:
if len(word) == naj:
ys.append(word)
return ', '.join(ys)
.py
Izpišite vse datoteke v trenutnem direktoriju, ki imajo končnico .py
.
Če se vam naloga zdi prelahka, poskusite napisati program, ki izpiše
vse datoteke s končnico .py
v trenutnem direktoriju in vseh
poddirektorijih trenutnega direktorija. Torej, če se nahajate v
direktoriju /home/glenda
, mora vaš program najti tako datoteko
/home/glenda/p9.py
, kot tudi datoteko
/home/glenda/plan9/from/outer/space.py
.
Rešitev
import os
for f in os.listdir():
if os.path.splitext(f)[1] == '.py':
print(f)
Poglejmo si iterativno rešitev težje naloge. Iterativna rešitev nam je všeč,
ker uporablja samo konstrukte, ki jih že poznamo:
ds = ['.']
while ds:
d = ds.pop()
for f in os.listdir(d):
f = os.path.join(d, f)
if os.path.isdir(f):
ds.append(f)
elif os.path.splitext(f)[1] == '.py':
print(f)
Težjo nalogo lahko rešimo tudi z uporabo rekurzije.
def list(path):
for f in os.listdir(path):
f = os.path.join(path, f)
if os.path.isdir(f):
list(f)
elif os.path.splitext(f)[1] == '.py':
print(f)
list('.')
Ali pa uporabimo funkcijo os.walk.
for dirpath, dirnames, filenames in os.walk('.'):
for filename in filenames:
if os.path.splitext(filename)[1] == '.py':
print(os.path.join(dirpath, filename))
ID3v1
Napiši funkcijo, ki v podanem direktoriju prebere vse datoteke s končnico .mp3 in sestavi prikazan izpis:
Title: Nocoj
Artist: Slon in Sadez
Album: Sponsorska plata - NeCenzurira
Year: 2010
File: 10 Slon in Sadez - Nocoj.mp3
Title: Opozorilo
Artist: Slon in Sadez
Album: Sponsorska plata - NeCenzurira
Year: 2010
File: 17 Slon in Sadez - Opozorilo.mp3
Podatke o pesmi ne smeš prebrati iz imena datoteke ampak iz njene
vsebine. To storiš tako, da prebereš zadnjih 128 znakov datoteke. Če
prvi trije znaki tega niza niso enaki "TAG"
potem datoteka podatkov o
izvajalcih ne vsebuje in jo je treba preskočiti. Sicer se v naslednjih
30 znakih nahaja naslov pesmi, v naslednjih 30 ime izvajalca, v
naslednjih 30 ime albuma in naslednjih 4 leto izdaje. Če je naslov
pesmi, ime izvajalca ali albuma krajše od 30 znakov, je na koncu niza
dodano ustrezno število znakov "\x00"
, ki jih boš moral odstraniti.
Za testiranje lahko uporabiš izbrani pesmi Slona in Sadeža iz prosto dostopne Sponzorske plate.
Rešitev
import os
def id3v1(dir):
os.chdir(dir)
for fn in os.listdir():
if os.path.splitext(fn)[1] == '.mp3':
b = open(fn, 'rb').read()[-128:]
if b[:3] != b'TAG': continue
b = b[3:]
for key, size in [('Title', 30), ('Artist', 30), ('Album', 30), ('Year', 4)]:
print('{:>6}: {}'.format(key, b[:size].strip(b'x00').decode('ascii')))
b = b[size:]
print(' File:', fn)
print()
id3v1('sponzorska_plata')
Plagiator
Razpakirajte direktorij z desetimi datotekami in poiščite plagiatorja! Napišite program, ki ugotovi v katerih dveh datotekah se ponovi vsaj 1000 znakov.
Rešitev
Odgovor je 3.txt in 8.txt. Počasnejša rešitev (čas izvajanja: 200 s)datoteke = [open('datoteke/{}.txt'.format(i)).read() for i in range(10)]
for i in range(10):
for j in range(i):
for k in range(0, len(datoteke[i]) - 1000):
if datoteke[i][k:k + 1000] in datoteke[j]:
print(i, j)
Hitrejša rešitev (čas izvajanja: < 1 s)
Ta rešitev ni več povsem pravilna, saj se lahko zgodi, da vrne tudi imena datotek v katerih se ponovi 500 znakov, nikoli pa ne spregleda datotek v katerih se ponovi vsaj 1000 znakov.
datoteke = [open('datoteke/{}.txt'.format(i)).read() for i in range(10)]
for i in range(10):
for j in range(i):
for k in range(0, len(datoteke[i]) - 500, 500):
if datoteke[i][k:k + 500] in datoteke[j]:
print(i, j)