Python

  • Python este un limbaj interpretat. Interpretorul citeste linie dupa line din program si semnaleaza codul care nu are sens pe masura ce il ruleaza.

  • Python este caracterizat ca fiind dynamically typed. Ce inseamna aceasta caracteristica?

  • Comparativ cu limbajul C in care se declara tipul variabilelor, al parametrilor unei functii sau tipul de date returnat de o functie, in Python nu se fac declaratii de tip, ci se identifica tipul datelor in timpul rularii.

Tipuri de date in Python

  • Tipurile de date numerice in Python sunt int, long, float, complex. Mai exista si tipul boolean ca subtip al intregilor.
  • Tipul int este implementat ca tipul long in C, adica pe 32 de biti. Tipul long din Python are precizie nelimitata, iar float este implementat ca double in C. Tipul complex il vom studia semestrul 2 in detaliu, in conexiune cu studiul semnalelor analogice si discrete.

Sa exemplificam ce se afiseaza apeland type(data):

In [1]:
n=2
print type(n)
<type 'int'>
In [2]:
x=23.75
type(x)
Out[2]:
float
In [3]:
b=False
c=True
print b
type(c)
False
Out[3]:
bool
  • In Python exista si tipul de date sir. Relevante pentru abordarile noastre sunt string-urile, listele si tuple-urile.
In [4]:
s='acesta un string'
type(s)
Out[4]:
str
In [5]:
ss="si acesta este un string"
type(ss)
Out[5]:
str
In [6]:
L=len(ss)

print 'Lungimea stringului ss este ', L
Lungimea stringului ss este  24

Caracterul din pozitia i, i=0,1,2, ..., len(string)-1 se acceseaza ca ss[i]:

In [7]:
print ss[12]
t

Un element al unui string nu poate fi modificat:

In [8]:
ss[1]='u'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-46468ec3f542> in <module>()
----> 1 ss[1]='u'

TypeError: 'str' object does not support item assignment
  • O lista in Python este o colectie de date de acelasi tip sau date de tipuri diverse. Colectia de date (elemente ale listei) se insereaza intre paranteze drepte [, ], iar doua elemente succesive se separa prin virgula:
In [9]:
Lista=[2,4,6,8]
lung=len(Lista)

print lung, Lista[3]
4 8
In [10]:
LL=[3, 'w', "text", 3.14]
print type(LL)
print LL[2]
<type 'list'>
text

Elementele unei liste pot fi alte liste:

In [11]:
Li=[[2,3,5], [1,6,8], [9,1]]
print Li[1]

Li[1]='inserez string'
print Li
[1, 6, 8]
[[2, 3, 5], 'inserez string', [9, 1]]

Se poate defini si o lista vida: L=[]

Atat unei liste vide cat si unei liste cu cel putin un element i se pot adauga elemente astfel: NumeLista.append(element)

In [12]:
L=[]
L.append(5)
L.append('hei')
print L
L.append('c')
print L
[5, 'hei']
[5, 'hei', 'c']
  • Tipul de date tuple este echivalentul n-uplului definit la Algebra, adica este un set ordonat de n elemente, n>=1. Elementele unui tuple se separa prin virgula si sunt inserate intre doua paranteze rotunde: t=(3,4,2)
In [13]:
tu=(2,)
tup=(3,5)
print tu, tup
print tup[0], tup[1]
(2,) (3, 5)
3 5

Un tuple cu un singur element se specifica indicand intre paranteze rotunde elementul, urmat de virgula (vezi tuple-ul tu de mai sus).

Un tuple, la fel ca un string, este invariabil (immutable in l engleza), adica elementele sale nu pot fi actualizate:

In [14]:
t=(5,2,7)
t[2]=4
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-5b914efccfb1> in <module>()
      1 t=(5,2,7)
----> 2 t[2]=4

TypeError: 'tuple' object does not support item assignment

In problemele de Algebra liniara vom folosi un tuple de 1 sau 2 elemente pentru a declara dimensiunile unui array.

Se poate defini si o lista de tuples:

In [15]:
L=[(2,5), (1,2,7), (8,)]
print L[2]
print len(L[1]), len(L[2]), 
(8,)
3 1

Elementele unui tuple nu trebuie sa fie obligatoriu de tip numeric. De exemplu putem defini:

In [16]:
t=(5, 'nota de salvare', 10, 'nota de excelenta')
print t
print t[0:2:4]
(5, 'nota de salvare', 10, 'nota de excelenta')
(5,)

Operatii cu tuple-uri:

In [17]:
t=(2,3,5)
s=(6,7,0)
print t+s
(2, 3, 5, 6, 7, 0)

Observam ca suma a doua tuple-uri are ca efect concatenarea lor.

In concluzie: elementele unui string sunt doar caractere, in timp ce elementele unei liste sau tuple pot avea orice tip.

Slicing in Python

Stringurile, listele si tuple-urile pot fi sectionate (feliate) si se pot apela/afisa doar o parte din ele. O asemenea operatie se numeste slicing.

Daca S este string, lista sau tuple de lungime, len(S), egala cu N, atunci urmatoarele notatii de slicing semnifica:

S[i:], subsirul de elementele S[i], ..., S[N-1]

S[:i], subsirul de elemente S[0], ..., S[i-1]

S[i:j], subsirul de elemente S[i],..., S[j-1]

S[i:j:p], subsirul de elemente ale lui S incepand cu S[i] si parcurs cu pasul p>1 pana la elementul din pozitia maxima i+k*p<j,

In [18]:
S='Python pune la dispozitie operatii speciale'
L=len(S)
print L
print S[15:]
print S[:15]
print S[15:20]
print S[1:18:2]
43
dispozitie operatii speciale
Python pune la 
dispo
yhnpn ads
In [19]:
t=(2,4,6,8)
ta=t[:2]
tb=t[1:]
print ta, tb
(2, 4) (4, 6, 8)

Indentarea in Python

Spre deosebire de limbajul C, in care delimitarea blocurilor de program se realizeaza incluzand blocul respectiv intre acolade {, }, in Python se foloseste indentarea, adica liniile unui bloc incep din aceeasi coloana (se lasa acelasi numar de blank-uri pana la primul caracter al liniilor).

Regula de indentare este urmatoarea: liniile de cod neincluse intr-o bucla for, intr-o secventa if-else sau while sau inca in corpul unei functii, incep de obicei din pozitia initiala a liniei.

In [20]:
x=2
y=x+ int(2.3)
print y
4
In [21]:
x=5
  n=7
  print x, n  
  File "<ipython-input-21-4197e8957835>", line 2
    n=7
    ^
IndentationError: unexpected indent

In Python sfarsitul unei linii de cod nu se marcheaza uzual cu punct si virgula, dar daca inseram ; interpretorul il ignora.

Bucla for

In [22]:
n=5
x=[]

for i in range(n):
    x.append(2*i)
    x.append('impar?')
print  x  
[0, 'impar?', 2, 'impar?', 4, 'impar?', 6, 'impar?', 8, 'impar?']
  • linia unui for se termina obligatoriu cu doua puncte.

  • for i in range(n) este echivalentul lui for(i=0;i<n;i++) din C/C++.

  • blocul din bucla for este indentat;

Sintaxa instructiunii if-else

In [23]:
n=5
if n==2:
   print 'n este egal cu 2'
else:
   print 'n este diferit de 2'
n este diferit de 2

Remarcam ca se scrie
if conditie:

else:

si ca blocurile aferente sunt identic indentate!!!

Operatorii relationali din Python sunt: <, <=, >, >=, ==, !=

Acesti operatori au aceasi semnificatie ca in C. Ei se folosesc in problemele de Algebra liniara pentru a compara scalari si array-uri. O comparatie returneaza True sau False.

In [24]:
x=2
y=5.73
z=x>=y
print z
False

Operatorii logici in Python sunt and, or si not:

In [25]:
a=2
b=0

if a<b and a>0:
    print 'primul caz'
else:
    if a>=b or a<0:
        print 'al doilea caz'
    else:    
        print 'al treielea caz'    
        
al doilea caz

Operatorii de apartenenta sunt in si not in.

In [26]:
L=['a', 'b', 'c', '*', '#']
if '@'in L:
    print 'pot trimite un email'
else:
    if '$' not in L:
        print 'n-am dolari, nu pot trimite scrisoare'  
    else:
        print 'merg la posta'
n-am dolari, nu pot trimite scrisoare

Definirea functiilor in Python

Ca in orice limbaj de programare functiile se folosesc pentru a defini cod reutilizabil, dar si pentru a organiza codul.

Linia de definitie a unei functii este de forma:

def NumeFunctie(param1, param2, ..., paramN):

  • def este un cuvant rezervat, care indica definitia unei functii.

  • numele functiei se alege conform acelorasi reguli ca in C.

  • parametrii param1, param2, ..., param N sunt nume si ele definesc tipurile de argumente pe care functia le poate accepta.

  • linia de definitie se incheie obligatoriu cu :

  • liniile ce constituie corpul functiei sunt indentate.

Pentru a ilustra modalitatea de indentare, dam un exemplu elementar de functie ce calculeaza cel mai mare divizor comun a doua numere:

In [27]:
def cmmdivc(m,n):
    cmmd=1
    d=2 # d posibil divizor
    while d<=m and d<=n:
        if m%d==0 and n%d==0:
            cmmd=d
        d+=1    
    return cmmd

#############################
# apelam functia:
nrdiv=cmmdivc(6,15)
print nrdiv
        
3

Indentarea indica in mod evident sub-blocurile din corpul functiei.

Functiile pot fi privite ca orice alt obiect (float, tuple, etc). Invocand tipul unei functii prin type(NumeFunctie) este afisat tipul function.

In [28]:
def doarprint():
    print  'Exemplu'
    return None

doarprint()
type(doarprint)
Exemplu
Out[28]:
function

Functia poate returna o valoare numerica sau orice alt obiect: lista, tuple, string, array, etc In exemplul de mai sus functia nu returneaza nimic. Este admis in acest caz sa se scrie simplu doar return sau sa nu se insereze return.

Operatii, functii si metode pentru liste

Deoarece listele de elemente numerice pot fi convertite in array-uri(obiectele de baza in Algebra liniara) prezentam cateva detalii relativ la liste.

  • stergerea elementului din pozitia i a listei L: del L[i]

  • Suma a doua liste L1+L2 are ca efect concatenarea lor;

  • produsul unei liste cu un numar intreg pozitiv, n*L, are ca efect generarea unei liste in care se repeta de n ori elementele listei L;

In [29]:
L=[2,3,-1, 5]
del L[2]
print L
[2, 3, 5]
In [30]:
L1=[2,3,4]
L2=[5,6,7]
L3=['a', 'b']
print L1+L2
print L2+L3
[2, 3, 4, 5, 6, 7]
[5, 6, 7, 'a', 'b']
In [31]:
L=[1,9]
LL=4*L
print LL
[1, 9, 1, 9, 1, 9, 1, 9]
  • test de apartenenta a unui element la o lista:
In [32]:
L=[2,3,3,4]
b= 3 in L
print b
True
In [33]:
L=[2,4,6,5]
if 7 in L:
    print 'Lista il contine pe 7'
else:
    print '7 nu e in lista'
7 nu e in lista
  • Iterarea unei liste:
In [34]:
L=[5,7,9,1,3]
for elem in L:
    print elem
    
5
7
9
1
3

Remarcam ca in iterare elem parcurge elementele listei, deci acest for este diferit de bucla for in care contorul parcurge multimea de indici ale elementelor listei:

In [35]:
for i in range(len(L)):
    print L[i]
5
7
9
1
3
  • Indexare cu indici negativi

Indexand elementele unei liste uzual, [L[0], L[1], ..., L[N-1]], se poate accesa elementul din pozitia i, prin L[i], i=0,1, ...N-1, asa cum am precizat deja.

Lista mai poate fi interpretata ca avand elementele L[N-N], L[N-(N-1)], ...L[N-1]. In aceasta interpretare un element arbitrar, L[N-i], se poate accesa si ca L[-i], i=1, 2, ..., N:

In [36]:
L=[2,4,6,8,10]
N=len(L)

print L[4]
print L[N-3], L[-3]
10
6 6

Functii ce actioneaza asupra listelor

Functiile min(L), max(L) returneaza elementul din lista cu cea mai mica valoare, respectiv cea mai mare valoare.

In [37]:
L=[3, -5, 2,1,7, 4, 9, 2]
print min(L), max(L)
-5 9

list(NumeTuple) converteste un tuple in lista:

In [38]:
t=(3,4)# acesta este un tuple
lt=list(t)
print t, lt
(3, 4) [3, 4]

Metode

Functiile sunt secvente de cod, apelate prin NumeFunctie(argumente). Metodele sunt functii asociate unui obiect, in acest caz unei liste.

O metoda pentru liste se apeleaza astfel: NumeLista.NumeMetoda(argumente)

In [39]:
#L.append(elem) adauga elementul elem  la lista

L=[4,5,2,7]
L.append(2)
print L

# nr=L.count(elem) este numarul de cate ori elementul elem apare in lista
L=[0, 1, 2, 3 ,4, 5, 6,5]
nr=L.count(5)
print '5 apare de ', nr, 'ori'
[4, 5, 2, 7, 2]
5 apare de  2 ori
In [40]:
# L.index(elem)indica primul indice la care apare elementul elem in lista
L=[-2, 1, 7, 3, 7]
pind=L.index(7)
print pind
2
In [41]:
print L
# L.insert(i,elem) insereaza elementul elem in pozitia L[i] 
#si deplaseaza elementele din dreapta cu o pozitie
L.insert(1, 10)
print L
[-2, 1, 7, 3, 7]
[-2, 10, 1, 7, 3, 7]
In [42]:
L=[1,2,5, 3,4,6]
#L.remove(elem) sterge elementul elem din lista
L.remove(5)
print L
[1, 2, 3, 4, 6]

Daca insa un element apare de mai multe ori in lista atunci L.remove(elem) sterge doar elementul din pozitia cu cel mai mic indice.

In [43]:
L=[1,2,3,4,5,4,7]
L.remove(4)
print L
[1, 2, 3, 5, 4, 7]
In [44]:
#L.sort() sorteaza elementele in ordine crescatoare
Lista=[2,5,3,1,4,6]

Lista.sort()
print Lista
[1, 2, 3, 4, 5, 6]
In [45]:
#L.reverse()  inverseaza pozitia elementelor in lista de lungime N: 
#elementul L[0] trece in pozitia N-1, L[1] in N-2, etc

L=[4, -2, 6, -3, 8,-4]
L.reverse()
print L
[-4, 8, -3, 6, -2, 4]

Generarea unei liste prin comprehensiune

In Python exista o modalitate de a crea liste, numita list comprehension. Aceasta modalitate este foarte naturala si simpla, inspirata de modul de definire a unor multimi finite in matematica (Guido Van Rossum, creatorul lui Python are un background de matematician), si anume: $S=\{ 3i-1\:|\: i=\overline{100,499}\}$.

Lista care are aceleasi elemente ca $S$ se descrie prin comprehensiune astfel:

In [46]:
L=[3*i-1 for i in range(100,500)]
print L[:5]# printam doar primele 5 elemente

LL=[elem+2 for elem in L]
print LL[:5]
[299, 302, 305, 308, 311]
[301, 304, 307, 310, 313]

Sintaxa de baza pentru generarea unei liste prin comprehensiune este deci:

L=[expresie for indice in range(m,n)]

sau

LL=[expresie for element in li]

unde li este o lista definita in prealabil.

In primul caz expresie este o functie de indice, iar in al doilea o functie de element.

In [1]:
from IPython.core.display import HTML
def  css_styling():
    styles = open("./custom.css", "r").read()
    return HTML(styles)
css_styling()
Out[1]: