Programiranje 2 2021/22 (Pii)

Delo s podatki v programskem jeziku Python

Splošnonamenski programski jezik Python je trenutno najpopularnejši jezik zaradi enostavne sintakse in obilice prosto-dostopnih programskih knjižnic, dočim pa ni najhitrejši jezik. Jezik se interpretira, kar pomeni, da program demo.py v ukazni vrstici izvedemo kot python demo.py.

Programming is not science, it is a skill! If you want to run as fast as Usain Bolt, you have to do a lot of running. There is no other way! And it is the same with programming. Just try to run a lot =)

Programske knjižnice in skripte

V programskem jeziku Python knjižnice in skripte uvozimo z ukazom import. Knjižnice je potrebno uvoziti pred uporabo, dočim obstajajo različne oblike uporabe ukaza import.

import demo
import requests
import requests as req
from requests import *

Programske zbirke podatkov

V programskem jeziku Python nabor določimo z običajnimi oklepaji (...) pri čimer ni potrebno, da so elementi nabora enakega tipa. Nabor je urejena nesprejemljiva zbirka podatkov kar pomeni, da ne moremo dodajati ali brisati elementov.

t = (0, 1, 'foo', 'bar')
st = t[:2]
ln = len(t)

V programskem jeziku Python seznam določimo z oglatimi oklepaji [...] pri čimer ni potrebno, da so elementi seznama enakega tipa. Seznam je urejena sprejemljiva zbirka podatkov kar pomeni, da lahko dodajamo ali brišemo elemente po vrednosti in indeksu.

l = [0, 1, 'foo', 'bar']
sl = l[:2]
ln = len(l)
l[1] = -1
del l[0]
l.remove(-1)
l.append(9.81)
l.extend([0, 'baz'])

V programskem jeziku Python množico določimo z zavitimi oklepaji {...} ali ukazom set() pri čimer ni potrebno, da so elementi množice enakega tipa. Množica je neurejena sprejemljiva zbirka podatkov kar pomeni, da lahko dodajamo ali brišemo elemente po vrednosti.

s = {0, 1, 'foo', 'bar'}
ln = len(s)
s.remove(1)
s.add(9.81)
s.update([0, 'baz'])

V programskem jeziku Python slovar določimo z zavitimi oklepaji {...} ali ukazom dict() pri čimer ni potrebno, da so ključi ali vrednosti slovarja enakega tipa. Slovar je neurejena sprejemljiva zbirka podatkov kar pomeni, da lahko dodajamo ali brišemo vrednosti po ključu.

d = {0: 'foo', 'bar': 1}
ln = len(d)
d[1] = 'baz'
d.pop('bar')
d.update({'bar': 1})
l = dict.values()
l = dict.keys()

V programskem jeziku Python zbirko uredimo z uporabo funkcije sorted, ki vrne urejen seznam elementov, dočim morajo biti elementi enakega tipa. Na drugi strani pa metoda shuffle ustvari naključno permutacijo elementov seznama, dočim ni potrebno, da so elementi enakega tipa.

s = {'foo', 'bar', 'baz'}
l = sorted(s)

import random
random.shuffle(l)

Kaj vrneta funkciji iter in enumerate, če ju uporabimo nad Python zbirko? Slednja se izkaže kot uporabno, ko iteriramo čez elemente zbirke in hkrati potrebujemo indeks (tj. zaporedno številko) elementa.

Branje podatkov iz datoteke

V programskem jeziku Python datoteko odpremo s funkcijo open, beremo z uporabo funkcij read ali readline in zapremo z metodo close. Pri tem je priporočena uporaba programskega konstrukta with open(..., 'r') as ..., ki po koncu branja samodejno zapre datoteko. Vsebino datoteke lahko preberemo v celoti, dočim navadno beremo zaporedoma po vrsticah.

file = open('file.txt', 'r')
print(file.readline())
print(file.read())
file.close()

file = open('file.txt', 'r')
for line in file:
  print(line)
file.close()

with open('file.txt', 'r') as file:
    for line in file:
        print(line)

Pisanje podatkov v datoteko

V programskem jeziku Python datoteko odpremo s funkcijo open, pišemo z uporabo metode write in zapremo z metodo close. Pri tem je priporočena uporaba programskega konstrukta with open(..., 'w'|'a') as ..., ki po koncu pisanja samodejno zapre datoteko. Vsebino datoteke lahko zapišemo v celoti, dočim navadno pišemo zaporedoma po vrsticah.

file = open('file.txt', 'w')
file.write('line\nline\n')
file.write('line\n')
file.close()

with open('file.txt', 'w') as file:
    for i in range(10):
        file.write('{:d}. line\n'.format(i + 1))

Luščenje vsebine spletnih strani

V programskem jeziku Python spletno stran preberemo z uporabo programskih knjižnic http.client, requests ali drugih. Pri tem spletno stran vedno preberemo v celoti, dočim lahko naknadno iteriramo po vsebini spletne strani z uporabo programskih zank.

Primer uporabe Python knjižnice http.client je prikazan spodaj.

import http.client
conn = http.client.HTTPSConnection('urnik.fmf.uni-lj.si')
conn.request('GET', '/letnik/44/')
text = conn.getresponse().read().decode()
for char in text:
  print(char)

Primera uporabe Python knjižnice requests je prikazan spodaj.

import requests
req = requests.get('https://urnik.fmf.uni-lj.si/letnik/44/')
text = req.text
for char in text:
  print(char)
  
req = requests.get('http://ip.jsontest.com/')
json = req.json()
for elem in json:
  print(elem)

Razčlenjevanje nizov z regularnimi izrazi

V programskem jeziku Python regularne izraze uporabljamo za razpoznavanje, razčlenjevanje in iskanje nizov znakov. Regularni izraz predstavlja želeni oziroma iskani vzorec znakov, ki ga definiramo kot r'...'. Pri tem lahko uporabljamo rezervirane znake oziroma vzorce naštete spodaj.

(Rezervirane) znake oziroma vzorce lahko združujemo, ponavljamo in gnezdimo kot je našteto spodaj.

Pri delu z regularnimi izrazi navadno uporabljamo Python knjižnico re (https://docs.python.org/3.9/library/re.html).

Funkcija match preveri ali začetek niza znakov ustreza podanemu regularnemu izrazu. Funkcija vrne None, če se niz ne začne z regularnim izrazom, sicer pa objekt razreda Match, ki vrne ujemanje z uporabo funkcije group.

import re
string = '-123.45'
regex = r'[+-]?[1-9][0-9]*'
res = re.match(regex, string)
if res == None:
    print('Not integer!')
else:
    print(res.group())

Funkcija search preveri ali niz znakov vsebuje podani regularni izraz. Funkcija vrne None, če niz ne vsebuje regularnega izraza, sicer pa objekt razreda Match, ki vrne ujemanje z uporabo funkcije group.

import re
string = 'Is this integer -123?'
regex = r'[+-]?[1-9][0-9]*'
res = re.search(regex, string)
if res == None:
    print('No integer found!')
else:
    print(res.group())

Funkcija findall poišče vse pojavitve podanega regularnega izraza v nizu znakov. Funkcija vrne seznam ujemanj regularnega izraza, ki je lahko prazen.

import re
string = 'Find all integers in 123.45!'
regex = r'[+-]?[1-9][0-9]*'
res = re.findall(regex, string)
for int in res:
    print(int)

Funkcija split razbije niz znakov glede na podan regularni izraz. Funkcija vrne seznam razbitja niza znakov, ki je lahko prazen.

import re
string = 'Split by integers -123 and 45!'
regex = r'[+-]?[1-9][0-9]*'
res = re.split(regex, string)
for str in res:
    print(str)

Funkcija sub zamenja vse pojavitve podanega regularnega izraza v nizu znakov. Pri tem lahko zamenjavo določimo kot niz znakov…

import re
string = 'Replace integers 123 and 45!'
regex = r'[+-]?[1-9][0-9]*'
res = re.sub(regex, '<int>', string)
print(res)

…ali pa zamenjavo določimo z uporabo podane funkcije.

import re
string = 'Replace integers -123 and 45!'
regex = r'[+-]?[1-9][0-9]*'
# def replace(res):
#   return 'x' * len(res.group())
replace = lambda res: 'x' * len(res.group())
res = re.sub(regex, replace, string)
print(res)