Natural Language Processing

Laboratorul 2

(Deadline: 31.03.2024 23:59:59)

Daca nu sunteti logati exercitiile nu se mai afiseaza.

Functii - aprofundare

Valori default pentru parametri

def f(x=1,y=2,z=3):
    return x+y+z

print(f())
print(f(100))
print(f(100, 100))
print(f(100, 100, 100))
Va afisa: 6
105
203
300

Apel cu numele parametrilor

def f(x=1,y=2,z=3):
    return x+y+z

print(f(y=100))
print(f(z=100, x=100))
Va afisa: 104
202

Functii cu numar variabil de argumente

def inmultire(*args):
    r=1
    for x in args:
        r*=x
    return r

print(inmultire(2,3,1,5,10))
Va afisa: 300

Daca avevm o functie definita cu numar variabil de argumente si totusi argumentele pe care vrem sa le transmitem sunt intr-o lista, de exemplu lst=[2,3,1,5,10] vom apela functia cu *lst in locul enumerarii argumentelor. Deci pentru functia de mai sus, am apela inmultire(*lst).

Argumentele programului

Uneori dorim sa apelam programul cu anumite argumente. In acest caz scriem in linia de comanda ceva de genul: python programel.py arg1 arg2 arg3 ......

Pentru a accesa argumentele trebuie sa importam modulul sys: import sys si apoi iteram prin lista sys.argv. Atentie, primul argument este numele programului.

Instructiunea vida

Instructiunea vida este instructiunea pass. Aceasta nu face nimic si adesea e folosita pe post de placeholder. De exemplu, pentru o functie pe care dorim sa o declaram ca sa nu uitam de ea dar inca nu dorim sa o definim am putea scrie: def f():
    pass

Multimi

Multimile sunt colectii in care elementele sunt distincte. Elementele se enumera intre acolade. Multimile pot fi definite si cu ajutorul constructorului set(), dandu-se ca parametrul o lista de elemente

Multimea vida nu se poate defini doar prin acolade fara continut, fiindca este simbolul dictionarului vid. Asadar, pentru multime vida folosim constructorul fara parametri: m=set() E corect dar nu e indicat (deoarece avem versiunea mai scurta, fara parametri) sa scriem si asa: m=set([])

Putem itera prin multimi astfel: for elem in {1,2,3,4} :
    print(elem, end=' ')
Va afisa: 1 2 3 4

Multimile pot contine elemente de tipuri diferite. O multime poate contine doar elemente immutable (de exemplu o multime poate contine un sir sau tuplu, insa nu poate contine o lista, un dictionar sau chiar altv multime). Mai jos aevti un exemplu cu o multime cu elementele enumerate: m={2,1,"x",(1,2),2.3} sau m=set([2,1,"x",(1,2),2.3]) >>> m=set([1,2,1,2,2])
>>> m
{1, 2}

Operatii pe multimi

Consideram multimile: m1={1,3,5,8,9}
m2={2,3,7,8}

Reuniune
>>> reuniune = m1 | m2
>>> reuniune
{1, 2, 3, 5, 7, 8, 9}
Intersectie
>>> intersectie = m1 & m2
>>> intersectie
{8, 3}
Diferenta
>>> diferenta = m1 - m2
>>> diferenta
{9, 5, 1}
Diferenta simetrica
>>> diferenta_simetrica = m1 ^ m2
>>> diferenta_simetrica
{1, 2, 5, 7, 9}

Teste pe multimi

Consideram multimile: m2={2,3,7,8}
m3={2,3}

Apartenenta
>>> 2 in m3
True
>>> 2 not in m3
False
Incluziune
>>>
>>> m3<m2
True
>>> m3<=m2
True
>>> m2>=m2
True

Metode specifice

Consideram multimea: m3={2,3}

Cardinalul (functia len())
>>> len(m3)
2
Adaugare si stergere de elemente

Putem adauga un element cu metoda add() si sa stergem elementul cu discard() sau remove(). Diferenta intre discard si remove este ca remove arunca o exceptie daca elementul dat ca parametru nu exista >>> m3.add(10)
>>> m3
{10, 2, 3}
>>> m3.discard(10)
>>> m3
{2, 3}

Putem sterge si un element arbitrar din multime cu ajutorul metodei pop(): >>> m={1,2,3,4,5}
>>> m.pop()
1
>>> m
{2, 3, 4, 5}

Vidarea multimii (clear())
>>> m3.clear()
>>> m3
set()

Multimi immutable (frozenset)

Aceste multimi nu se pot modifica (nu putem adauga sau sterge elemente). Asadar pot fi elemente in alte multimi (immutable sau nu). >>> m=frozenset(["Elsa","Anna","Olaf","Kristoff","Hans"])
>>> m
frozenset({'Olaf', 'Elsa', 'Hans', 'Anna', 'Kristoff'})
>>> mnr=frozenset([1,2,3])
>>> mm={m,mnr}
>>> mm
{frozenset({'Olaf', 'Elsa', 'Hans', 'Anna', 'Kristoff'}), frozenset({1, 2, 3})}

Cateva functii utile

Mai jos sunt enumerate cateva functii predefinite utile:

Functia any()

Functia any() primeste ca parametru o colectie (iterabila) si returneaza True daca cel putin un element are valoarea True (sau poate fi convertit implicit la True). In caz contrar, returneaza False. Pentru o colectie vida va returna False. >>> any({1,2,3,0})
True
>>> any([0,0,0])
False
>>> any([])
False

Functia all()

Functia all() primeste ca parametru o colectie (iterabila) si returneaza True daca toate elementele au valoarea True (sau pot fi convertite implicit la True). In caz contrar, returneaza False. Pentru o colectie vida va returna True. >>> all({1,2,3,0})
False
>>> all({1,2,3})
True
>>> all([0,0,0])
False
>>> all([])
True

Functiile ord() si chr()

Functia ord primeste un caracter si returneaza codul ascii al acestuia. Functia chr primeste codul ascii si returneaza caracterul (sir de lungime 1) corespunzator. >>> ord("a")
97
>>> chr(97)
'a'

Functia zip()

Functia zip primeste ca parametru una sau mai multe colectii si returneaza un iterator. Elemente iterabile rezultate sunt tupluri cu proprietatea ca tuplul de pe pozitia i contine elementele de pe pozitia i din colectiile date ca argumente (ordinea din tuplu e data de ordinea in care au fost transmise colectiile ca argumente). >>> l1=["a","b","c"]
>>> zl1=zip(l1)
>>> zl1
<zip object at 0x0308A6E8>
>>> l_zl1=list(zl1)
>>> l_zl1
[('a',), ('b',), ('c',)]
>>>
>>> l3=[100,200,300,400]
>>> l_zl3=list(zip(l1,l3))
>>> l_zl3
[('a', 100), ('b', 200), ('c', 300)]

Functia eval()

Primeste ca parametru un sir pe care il evalueaza ca expresie. >>> eval("1+2-4")
-1

Expresii lambda

Functiile lambda sunt functii anonime de dimesniune mica. Executa doar o expresie. Forma generala este: lambda p1, p2, .. pn: expresie Expresia, depinde, evident, de parametrii functiei.

Exemplu: >>> q = lambda a : a**2
>>> q(10)
100
>>> w = lambda a, b, c: a+b+c
>>> w("xyz","uuu","hop")
'xyzuuuhop'
>>> type(w)
<class 'function'>

Un exemplu de folosire a functiilor lambda pentru sortarea listelor dupa alt criteriu decat cel default:

Exemplu: >>> l=["abc","z","baubau","wwww",""]
>>> l.sort()
>>> l
['', 'abc', 'baubau', 'wwww', 'z']
>>> l.sort(key=lambda x: len(x))
>>> l
['', 'z', 'abc', 'wwww', 'baubau']

Comprehensions

List comprehensions

Sintaxa: [expresie_element for parametru in element_iterabil]. >>> [x for x in range(10,20,2)]
[10, 12, 14, 16, 18]
>>> [x for x in "abcd"]
['a', 'b', 'c', 'd']

Se poate adauga si o conditie pentru elemente adaugate in lista. Sintaxa: [expresie_element for parametru in element_iterabil if conditie] >>> [x for x in "abracadabra" if x<"e"]
['a', 'b', 'a', 'c', 'a', 'd', 'a', 'b', 'a']

Pentru conditii putem folosi si expresii conditionale (diferenta este ca expresia pentru elementul generator - al carei rezultat se pune in lista - contine conditia): >>> [ "a"+str(x) if x<5 else "b"+str(x) for x in range(10)]
['a0', 'a1', 'a2', 'a3', 'a4', 'b5', 'b6', 'b7', 'b8', 'b9']

Putem combina expresii conditionale cu conditiile puse pentru comprehension: >>> [ "a"+str(x) if x<5 else "b"+str(x) for x in range(20) if x%3==0]
['a0', 'a3', 'b6', 'b9', 'b12', 'b15', 'b18']

Se pot pune mai multe expresii for in cazul in care elementele depind de mai multi parametri: >>> [x*10+y for x in range(3,8) for y in range(1,10,2) if x<y ]
[35, 37, 39, 45, 47, 49, 57, 59, 67, 69, 79]

Putem genera astfel chiar si matrici: >>> [0 for x in range(4)]
[0, 0, 0, 0]
>>> [[0 for x in range(4)] for y in range(4)]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

Set comprehensions

Au aceeasi forma ca si pentru liste, doar ca se scriu intre acolade: >>> {int(x) for x in str(100541)}
{0, 1, 4, 5}
>>> {(x,y) for x in [1,2,3,1] for y in [2,2,3]}
{(1, 2), (3, 2), (1, 3), (3, 3), (2, 3), (2, 2)}
>>> {(x,y) for x in [1,2,3,1] for y in [2,2,3] if x>=y}
{(3, 2), (3, 3), (2, 2)}

Dict comprehensions

Au aceeasi forma ca si pentru liste, doar ca se scriu intre acolade si elementul generator e de forma k:v >>> {k:k**3 for k in range(0,10)}
{0: 0, 1: 1, 2: 8, 3: 27, 4: 64, 5: 125, 6: 216, 7: 343, 8: 512, 9: 729}
>>> {k:[k**y for y in range(0,4)] for k in range(1,10)}
{1: [1, 1, 1, 1], 2: [1, 2, 4, 8], 3: [1, 3, 9, 27], 4: [1, 4, 16, 64], 5: [1, 5, 25, 125], 6: [1, 6, 36, 216], 7: [1, 7, 49, 343], 8: [1, 8, 64, 512], 9: [1, 9, 81, 729]}
>>> [(x,y) for x in range(1,4) for y in range(7,10)]
[(1, 7), (1, 8), (1, 9), (2, 7), (2, 8), (2, 9), (3, 7), (3, 8), (3, 9)]
>>> {k:v for k,v in [(x,y) for x in range(1,4) for y in range(7,10)]}
{1: 9, 2: 9, 3: 9}

Exceptii

def impartire_supraunit(x,y):
    try:
        if x<y :
            raise Exception("Primul argument trebuie sa fie mai mare sau egal decat al doilea.")
        return x/y
    except ZeroDivisionError:
        print("Al doilea argument nu poate fi zero")
    except TypeError as eroare:
        print("Argumentele nu sunt numere:"+str(eroare))
    except Exception as eroare:
        print(eroare)

        
 
print(impartire_supraunit(8,0))   
print(impartire_supraunit("x",10))
print(impartire_supraunit(5,10))
print(impartire_supraunit(10,5))

Fisiere

Fisierele se deschid cu functia open(cale_fisier, mod_deschidere). Modul de deschidere poate fi:

Metode I/O pentru fisiere

Pentru scriere folosim metoda write().

Pentru citirea intregului fisier folosim metoda read(). Ii putem da si un argument care reprezinta cate caractere sa citeasca (f.read(10)).

Pentru citirea unei anumite linii din fisier folosim metoda readLine(numar_linie).

Pentru citirea fisierului linie cu linie folosim metoda readLines() care va returna o lista cu toate liniile.

Putem itera prin liniile fisierului astfel: fisier = open("fis.txt", "r")
for linie in fisier:
    print(linie)

Metoda tell() returneaza pozitia cursorului in fisier, iar metoda seek() pozitioneaza cursorul in fisier intr-o anumita locatie.

Pentru a inchide fisierul folosim metoda close().

Tema