Sunteți pe pagina 1din 79

Python ro:Primii pai

Contents

1 Introducere 2 Folosind promptul interpretorului 3 Alegerea unui editor 4 Folosind un fiier surs 4.1 Cum funcioneaz 4.2 Programe Python executabile 5 Cum obinem ajutor 6 Rezumat

Introducere Vom afla acum ce trebuie fcut pentru a rula tradiionalul program Hello World n Python. Astfel vom nva cum s scriem, salvm i rulm programe Python. Sunt doua ci de a folosi Python pentru a rula un program folosind promptul interactiv al interpretorului sau folosind fiierul surs. Vom afla cum se folosesc ambele metode. Folosind promptul interpretorului Pornii interpretorul de la linia de comand introducnd python la prompt. Pentru utilizatorii de Windows, putei rula interpretorul din linia de comand dac avei setat corect variabila PATH. Dac folosii IDLE (de la Integrated Developpement Linux Environment), dati clic pe Start Programs Python 3.0 IDLE (Python GUI). Acum introducei print('Hello World') urmat de tasta Enter. Ar trebui s vedei ca rezultat cuvintele Hello World.
$ python Python 3.0b2 (r30b2:65106, Jul 18 2008, 18:44:17) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> print('Hello World') Hello World >>>

Observai c Python va da rezultatul comenzii imediat! Ceea ce tocmai ai introdus este odeclaraie Python singular. Folosim print pentru (nesurprinzator) a tipri orice valoare pe care io furnizm. Aici i furnizm textul Hello World i acesta este tiprit rapid pe ecran. Cum s prsii interpretorul Ca s prsii prompt-ul, tastai Ctrl-D dac folosii IDLE sau un shell Linux/BSD. n cazul consolei Windows (Command prompt), tastai Ctrl-Z urmat de tastaENTER. Alegerea unui editor nainte de a trece la scrierea de programe Python n fiiere surs avem nevoie de un editor pentru a crea aceste fiiere. Alegerea editorului este crucial. Trebuie ales la fel ca i mainile. Un editor bun v va ajuta s scriei programe Python uor, fcnd timpul petrecut o cltorie confortabil i v va ajuta s ajungei la destinaie (s v atingei obiectivul) ntro maniera rapid i sigur. O cerin de baz este evidenierea sintaxei [1] n care diferitele componente ale sintaxei sunt colorate de aa natur nct s poi vizualiza programul i rularea lui. Dac utilizai Windows, v recomand s folosii IDLE. IDLE face syntax highlighting i multe altele printre care faptul c v permite s rulai programele tot n IDLE. O not special: Nu folosii Notepad este o opiune rea fiindc nu face syntax highlighting i nu suport indentarea textului, ceea ce este foarte important n cazul nostru, aa cum vei vedea n continuare. Editoarele bune precum IDLE (i VIM) v vor ajuta automat s indentai textul. Dac utilizai Linux/FreeBSD, atunci avei o mulime de opiuni pentru editor. Dac suntei chiar la nceputul carierei de programator, poate o s preferai geany. Are interfa grafic cu utilizatorul i butoane speciale pentru compilat i rulat programele Python fr complicaii. Dac suntei programator experimentat, atunci probabil c folosii deja Vim sau Emacs. Nu mai e nevoie s precizm c acestea dou sunt cele mai puternice editoare i vei avea nenumrate avantaje din folosirea lor la scrierea de programe Python. Eu personal folosesc Vim pentru majoritatea programelor. Dac suntei programator nceptor, putei folosi Kate care este unul din favoritele mele. n cazul n care dorii s alocai timpul necesar nvrii lucrului cu Vim sau Emacs, v recomand s le nvai pe amndou, ntruct pe termen lung vei culege foloase mult mai mari. n aceast carte vom folosi IDLE, editorul nostru IDE cel mai recomandat. IDLE este instalat n mod implicit de ctre installerele Python pentru Windows i Mac OS X. Este disponibil i pentru Linux i BSD n coleciile (engl. repositories) respective. Vom explora folosirea mediului IDLE n capitolul urmtor. Pentru mai multe detalii, v rog s vizitai documentaia IDLE . Dac tot mai dorii s vedei i alte opiuni pentru editor, recomand cuprinztoarea list de editoare pentru Python i s optai. Putei alege i un IDE (Integrated Development Environment)

pentru Python. A se vedea lista de medii integrate (IDE) care suport Pythonpentru detalii suplimentare. Imediat ce vei ncepe s scriei programe Python mari, IDE-urile pot fi cu adevrat foarte folositoare. Repet, v rog s alegei un editor adecvat el poate face scrierea de programe Python mai distractiv i uoar. Pentru utilizatorii de Vim Exist o introducere bun despre Cum s faci Vim un IDE puternic pentru Pythonde John M Anderson. Pentru utilizatorii de Emacs Exist o introducere bun despre Cum s faci Emacs un IDE puternic pentru Python de Ryan McGuire. Folosind un fiier surs S ne ntoarcem la programare. Exist o tradiie ca de cte ori nvei un nou limbaj de programare, primul program pe care l scrii s fie programul Hello World tot ce face el este s afieze Hello World cnd l rulezi. Dup expimarea lui Simon Cozens [2], este incantaia tradiional ctre zeii programrii ca sa te ajute s nvei limbajul mai bine:) . Pornii editorul ales, introducei programul urmtor i salvai-l sub numele helloworld.py Dac folosii IDLE, dai clic pe File New Window i introducei programul de mai jos. Apoi clic pe File Save.
#!/usr/bin/python #Fisier: helloworld.py print('Hello World')

Rulai programul deschiznd un shell [3] i introducnd comanda python helloworld.py. Daca folosii IDLE, deschidei meniul Run Run Module sau direct F5 de pe tastatur. Rezultatul este afiat astfel:
$ python helloworld.py Hello World

Daca ai obinut rezultatul afiat mai sus, felicitri! ai rulat cu succes primul program n Python. n caz ca ai obinut un mesaj de eroare, v rog, tastai programul anterior exact ca n imagine i rulai programul din nou. De reinut c Python este case-sensitive [4] aadarprint nu este acelai lucru cu Print observai p minuscul n primul exemplu i P majuscul n al doilea exemplu. De asemenea, asigurai-v c nu exist spaii sau TAB naintea primului caracter din fiecare linie vom vedea mai trziu de ce este att de important.

CUM FUNCIONEAZ

S considerm primele dou linii din program. Acestea sunt numite comentarii orice s-ar afla la dreapta caracterului # devine comentariu i este util n special pentru documentarea cititorului programului. Python folosete comentarii numai pentru acest caz. Prima linie este numita linie shebang de fiecare dat cnd ncepe cu #! urmat de locaia unui program; asta spune sistemului nostru Linux/Unix c fiierul trebuie nteles prin acest interpretor atunci cnd este executat. O explicaie mai detaliat va fi prezentat n capitolele urmtoare. De reinut c putei rula oricnd programul pe orice platform specificnd interpretorul n linia de comand, ca n exemplul python helloworld.py . Important Folosii cu grij comentarii n programe pentru a explica detalii importante ale unor instruciuni Asta va ajuta cititorul s neleag mai uor ce face programul. Acel cititor putei fi dumneavoastr, peste ase luni! Comentariile sunt urmate de o declaraie Python. n cazul nostru apelm funcia print care pur i simplu tiprete pe ecran textul 'Hello World'. Vom nva despre funcii ntr-un alt capitol; ce trebuie reinut acum este c orice am fi pus n paranteze ar fi aparut pe ecran. n acest caz punem 'Hello World', ceea ce se poate numi string fii fr grij, vom explora mai trziu terminologia aceasta n detaliu.
PROGRAME PYTHON EXECUTABILE

Partea aceasta se aplic numai utilizatorilor de Linux/Unix, dar utilizatorii de Windows ar putea fi curioi n legtur cu prima linie din program. Pentru nceput, va trebui s dm fiierului permisiunea de a fi executabil folosind comanda chmod i apoi s rulmprogramul surs.
$ chmod a+x helloworld.py $ ./helloworld.py Hello World

Comanda chmod este folosit aici pentru a schimba [5] mod-ul fiierului dndu-i drept de execuie pentru toi [6] utilizatorii sistemului. Pe urm executm programul direct, specificnd locaia programului surs. Folosim ./ pentru a indica localizarea programului executabil n directorul curent. Pentru a face lucrurile i mai distractive, putei redenumi fiierul cu numele helloworld i l putei rula cu ./helloworld i tot va merge, folosind interpretorul de la locaia specificat pe primul rnd din fiier..

Ce e de fcut dac nu tim unde este localizat Python? Atunci putei folosi programul envspecific sistemelor Linux. Modificai primul rnd astfel:
#!/usr/bin/env python

Programul env la rndul lui va cuta interpretorul Python care va rula programul. Pn acum am putut s executm programele noastre doar dac tiam calea exact. Dar dac dorim s rulm programul din orice director? Putem s facem asta dac memorm programul ntrunul din directoarele listate n variabila de mediu PATH. Oridecte ori rulai vreun program, sistemul caut acel program n directoarele listate n variabila PATH i apoi ruleaz programul. Putem face programul nostru disponibil n orice director prin copierea programului ntrunul din directoarele din PATH.
$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/swaroop/bin $ cp helloworld.py /home/swaroop/bin/helloworld $ helloworld Hello World

Putem afia coninutul variabilei PATH folosind comanda echo i prefixnd numele variabilei cu caracterul $ pentru a-i transmite shell-ului c avem nevoie de valoarea acestei variabile. Observm c /home/swaroop/bin este printre directoarele din PATH, undeswaroop este numele de utilizator [7] pe care eu l folosesc n sistemul meu. Exist unul similar pentru numele de utilizator al fiecaruia pe sistemul su. Ca alternativ, putei aduga un director anume la variabila PATH se face executndPATH=$PATH:/home/swaroop/mydir unde '/home/swaroop/mydir' este directorul pe care eu vreau sa-l adaug la variabila PATH. Aceast metod este foarte util dac vrei s scriei scripturi utile pe care vrei s le rulai oricnd din orice locaie a sistemului. Seamn cu a-i crea propriile comenzi, precum cdsau orice alt comand pe care o execui n terminalul Linux sau DOS prompt. Atenie Din punctul de vedere al Python-ului, program sau script sau software nseamn acelai lucru! Cum obinem ajutor Dac avei nevoie repede de informaii despre vreo funcie sau declaraie din Python, atunci putei apela la functionalitatea inclus [8] help. Este foarte folositor, mai ales la promptul interpretorului. De exemplu rulai help(print) se va afia documentaia de asisten pentru funcia print folosit pentru afiarea pe ecran. Not

Tastai q pentru a iei din help. Similar, putei obine informaii despre aproape orice din Python. Folosii help() pentru a afla mai multe despre nsui help! n cazul n care avei nevoie de ajutor n legtur cu operatori precum return, atunci va trebui s-i punei n ghilimele (ca n help('return')) pentru ca Python s ineleag fr confuzie ce ncercai s facei. Rezumat Acum ar trebui s putei scrie, salva i rula cu uurin programe Python. Pentru ca ai devenit utilizator de Python, s mai nvm cteva concepte din Python.

Python ro:Elemente
Simpla tiprire a textului Hello World nu ajunge, aa-i? Vrei s facei mai mult de att vrei s preluai ceva intrri, s le prelucrai i s obinei un rezultat. Putem face asta n Python folosind constante i variabile. Contents

1 Constante literale 2 Numere 3 iruri


3.1 Ghilimele simple 3.2 Ghilimele duble 3.3 Ghilimele triple 3.4 Secvene de evadare 3.5 iruri brute 3.6 irurile sunt imuabile 3.7 Concatenarea literalilor ir 3.8 Metoda format

4 Variabile 5 Nume de identificatori 6 Tipuri de date 7 Obiecte

7.1 Exemplu: Folosirea variabilelor i a literalilor

8 Linii logice i linii fizice 9 Indentarea 10 Rezumat

Constante literale O constanta literal este un numr precum 5, 1.23, 9.25e-3 sau un ir [1] precum 'Acesta este un ir' sau "E string!". Se numete literal fiindc este folosit literal i folosim valoarea literalmente. Numrul 2 se reprezint ntotdeauna pe sine i nimic altceva este oconstant deoarece valoarea sa nu poate fi schimbat. De aici denumirea de constante literale. Numere Numerele n Python sunt de trei tipuri integer, float i complex.

Un exemplu de integer (rom. ntreg) este 2 care este un numr ntreg. Exemple de float sau floating point [2] sunt 3.23 i 52.3E-4. Notaia E indic puterile lui 10. n acest caz, 52.3E-4 nseamn 52.3 * 10-4. Exemple de numere complexe sunt (-5+4j) i (2.3 - 4.6j) Not pentru programatorii experimentai Nu exist un tip separat long int. Tipul implicit integer poate fi orice valoare mare.

iruri Un ir (engl. string) este o secven de caractere. irurile sunt n esen doar o succesiune de cuvinte. Cuvintele pot fi n limba englez sau n orice alt limb suportat de standardul Unicode, ceea ce nseamn aproape orice limb din lume. Not pentru programatorii experimentai Nu exist iruri ASCII pure pentru c Unicode este un superset al ASCII. Dac se impune n program un flux de octei codat ASCII, atunci folosii str.encode("ascii"). Pentru detalii, urmrii discuia pe acest subiect de la StackOverflow. Implicit, toate irurile sunt n Unicode. Aproape pot garanta c vei folosi iruri n aproape toate programele Python pe care le scriei, aa c acordai atenie prii urmtoare despre cum se folosesc irurile n Python.

GHILIMELE SIMPLE

Putei specifica iruri folosind ghilimele simple [3] precum 'Citeaza-ma referitor la acest subiect'. Tot spaiul alb precum SPACE i TAB sunt pstrate ca atare
GHILIMELE DUBLE [4].

irurile n ghilimele duble [5] funcioneaza la fel ca i cele n ghilimele simple. De exemplu"Cum te cheam?"
GHILIMELE TRIPLE

Putei specifica iruri care se ntind pe mai multe linii folosind ghilimele triple (engl. triple quotes) (" sau ). Putei folosi liber ghilimele simple dau duble n interiorul ghilimelelor triple. Iat un exemplu:
'''Acesta este un ir multi-linie. Aceasta este prima linie. Aceasta este a doua linie. 'Cum te numeti?', l-a intrebat. El a zis "Bond, James Bond". '''

SECVENE DE EVADARE

S presupunem c vrem s utilizm un ir care conine un apostrof (una din ghilimele simple) '. Cum o s specificm irul What's your name?. Nu-l putem specifica 'What's your name?' pentru c Python va confunda apostroful cu sfritul irului. ntr-un fel sau altul va trebui s specificm c acel apostrof face parte din ir, nu este un delimitator. Pentru aceasta se folosete o secven de evadare [6]. Specificm apostroful \' observai backslash-ul. Astfel putem specifica irul 'What\'s your name?'. Alt cale de a specifica acest ir este utilizarea ghilimelelor duble pentru delimitarea sirului. Problema apare i la includerea unei ghilimele duble ntr-un ir delimitat cu ghilimele duble. i pentru evadarea backslash-ului trebuie tot backslash \\. Dar dac am vrea s specificm un ir pe dou rnduri? O soluie este s folosim ghilimele triple cum am vzut mai devreme, dar putem s folosim o secven de evadare pentru sfritul liniei \n pentru a indica trecerea pe o linie nou. Un exemplu ar fi Aceasta este prima linie\nAceasta este a doua linie. Alt exemplu util de secven de evadare este pentru TAB \t. Exist mult mai multe, dar le-am prezentat aici pe cele mai folosite de noi. Un lucru notabil este c ntr-un ir un backslash la sfritul liniei arat continuarea irului pe linia urmtoare, fr s se adauge caracterul newline. De exemplu:
"Aceasta este prima propoziie. \ Aceasta este a doua propoziie".

este echivalent cu "Aceasta este prima propoziie. Aceasta este a doua propoziie".
IRURI BRUTE

Dac avei nevoie s specificai iruri n care s nu fie procesate secvene de evadare trebuie s folosii iruri brute [7] prefixnd irul cu r sau R. De exemplu r"Caracterul newline este indicat de \n".
IRURILE SUNT IMUABILE

Asta nseamn c odat create, nu mai pot fi modificate. Dei pare un lucru ru, nu este. Vom vedea n diferitele programe prezentate de ce asta nu este o limitare.

CONCATENAREA LITERALILOR IR

Dac se altura doi literali, ei sunt concatenai de Python automat. De exemplu 'What\'s ' 'your name?' este convertit automat n "What's your name?". Not pentru programatorii C/C++ Nu exist n Python un tip de date separat char. Nu exist nici o nevoie real de aa ceva, deci sunt sigur c n-o s-i ducei dorul. Not pentru programatorii Perl/PHP Reinei ca irurile delimitate de gihilimele simple sau duble sunt la fel, nu difer prin nimic. Not pentru utilizatorii de expresii regulare Folosii ntotdeauna iruri brute cand avei de-a face cu expresii regulare, altfel o s fie nevoie de multe cutri n urm pentru a gsi ce nu merge. De exemplu referinele retroactive [8] pot fi utilizate ca '\\1' sau r'\1'.
METODA FORMAT

Uneori vrem s construim iruri din alte informaii. Aici este folositoare metoda format().
#!/usr/bin/python # Fiier: str_format.py vrst = 25 nume = 'Swaroop' print('{0} are {1} de ani.'.format(nume, vrst)) print('De ce se joac {0} cu python-ul la?'.format(nume))

Rezultat:
$ python str_format.py Swaroop are 25 de ani. De ce se joac Swaroop cu python-ul la?

Cum funcioneaz:

Un ir poate folosi anumite specificaii i apoi poate apela metoda format pentru a substitui acele specificaii care corespund argumentelor metodei format. Observai prima folosire, unde folosim {0} i asta corespunde cu varibila nume care este primul argument al metodei format. Similar, a doua specificaie este {1} corespunzatoare variabilei vrst care este al doilea argument pentru metoda format. Observai c puteam obine acelai lucru prin concatenare: nume + ' are ' + str(vrst) + ' de ani', dar uite ce urt i predispus la erori este aceast cale. n al doilea rnd, conversia n ir este fcut automat de metoda format n locul unei conversii explicite. n al treilea rnd, folosind metoda format putem schimba mesajul fr s avem de-a face cu variabilele i reciproc. Ce face Python n metoda format este c nlocuiete valoarea fiecrui argument n locurile specificate. Pot exista i specificri mai detaliate, cum ar fi:
>>> '{0:.3}'.format(1./3) # zecimal (.) precizie de 3 zecimale pentru float '0.333' >>> '{0:_^11}'.format('hello') # umple pn la 11 caractere cu textul centrat i bordat cu underscore (_) '___hello___' >>> '{nume} a scris {carte}.'.format(nume='Swaroop', carte='Un pic de Python') # pe baz de cuvintecheie 'Swaroop a scris Un pic de Python.'

Detalii despre aceste specificaii de formatare sunt date n PEP 3101 (PEP=Python Enhancement Proposal). Variabile Folosirea exclusiv a literalilor poate deveni rapid plictisitoare avem nevoie s stocm orice informaie i s o prelucrm. Aici este locul variabilelor. Variabilele sunt exact ceea ce spune numele lor valoarea lor poate fi modificat, va s zic se poate stoca orice ntro variabil. Variabilele sunt nite mici zone din memoria calculatorului unde se stocheaz nite informaie. Spre deosebire de constante, e nevoie de a accesa aceast informaie, din acest motiv variabilele au nume. Nume de identificatori Variabilele sunt exemple de identificatori. Identificatorii sunt nume date pentru a identificaceva. Exist cteva reguli care trebuie s fie urmate la stabilirea identificatorilor:

Primul caracter al numelui trebui s fie o litera a alfabetului (majuscul ASCII, minuscul ASCII, caracter Unicode) sau underscore (_). Restul numelui identificatorului poate include i cifre (de la 0 la 9). Pentru numele de identificatori majusculele si minusculele sunt considerate diferite (engl. case-sensitive). De exemplu, myname i myName nu desemneaz aceeai variabil. Observai minuscula n n primul caz i majuscula N n al doilea.

Exemple de nume valide de identificator sunt i, __chiar_aa, nume_23, a1b2_c3 iresum _count.

Exemple de nume invalide de identificator sunt 2chestii, asta contine spaii i cal-breaz.

Tipuri de date Variabilele pot lua valori de diferite tipuri numite tipuri de date. Tipurile de baz sunt numere i iruri, despre care am discutat deja. n ultimele capitole vom nva cum s crem propriile noastre tipuri de date, folosind clase. Obiecte Reinei, Python consider c tot ce se folosete n program este obiect, n sens generic. n loc de a spune ceva-ul, spunem obiectul. Not pentru utilizatorii de POO Python este puternic orientat pe obiecte n sensul c toate sunt obiecte, inclusiv numerele, irurile i funciile. Acum vom vedea cum se folosesc variabilele mpreun cu literalii. Salvai urmtorul program i rulai-l. Cum se scriu programele Python De acum ncolo, procedura standard de a salva i rula programele Python este astfel: 1. Deschidei editorul preferat. 2. Introducei codul programului dat n exemplu. 3. Salvai-l ntrun fiier cu numele menionat n comentariu. Eu urmez convenia de a salva toate programele Python n fiiere cu extensia .py. 4. Rulai-l folosind interpretorul cu comanda python program.py sau folosii IDLE pentru a rula programe. De asemenea putei folosi metoda executabilcum am explicat mai devreme.
EXEMPLU: FOLOSIREA VARIABILELOR I A LITERALILOR

# Fiier: var.py i = 5 print(i) i = i + 1 print(i) s = '''Acesta este un ir multi-linie. Aceasta este linia a doua.''' print(s)

Rezultat:

$ python var.py 5 6 Acesta este un ir multi-linie. Aceasta este linia a doua.

Cum funcioneaz: Iat cum lucreaz programul: nti, atribuim valoarea constantei literale 5 variabilei ifolosind operatorul de atribuire (=). Aceasta linie este o declaraie deoarece susine c trebuie fcut ceva, n acest caz, conectm variabila i la valoarea 5. n continuare, tiprim valoarea lui i folosind declaraia print care, previzibil, tipreste valoarea variabilei pe ecran. Apoi adugm 1 la valoarea stocat n i i pstrm noul rezultat. Tiprim valoarea variabilei i obinem ce am prevzut, valoarea 6. Similar, atribuim literalul ir variabilei s i o tiprim. Not pentru programatorii n limbaje cu tipuri statice Variabilele sunt folosite prin simpla atribuire a unei valori. Nu este necesar nici o declaraie sau definiie de tip de date. Linii logice i linii fizice O linie fizic este ceea ce vedei cnd scriei programul. O linie logic este ceea ce vede Python ca o singur declaraie. Python presupune implicit c fiecare linie fiziccorespunde unei linii logice. Un exemplu de linie logic este o declaraie precum print('Hello World') dac aceasta este singur pe linie (cum se vede n editor), atunci ea corespunde i unei linii fizice. Implicit, Python ncurajeaz folosirea unei singure linii logice pe linia fizic (rnd), ceea ce face codul mult mai lizibil. Dac vrei s specificai mai mult de o linie logic pe linie fizic, va trebui s specificai explicit ncheierea liniei logice cu (;). De exemplu,
i = 5 print(i)

este efectiv la fel ca


i = 5; print(i);

i acelai lucru poate fi scris


i = 5; print(i);

sau chiar
i = 5; print(i)

Totui, recomand cu trie s rmnei la scrierea cel mult a unei singure linii logice pe fiecare linie fizic. Prin folosirea mai multor linii logice pe o linie fizic se obine realmente cod mai lung. Ideea este s se evite semnul punct i virgul la maxim posibil pentru a obine un cod ct mai lizibil. De fapt, eu n-am folosit niciodat i nici n-am vzut punct i virgul ntr-un program Python. S dm un exemplu de linie logic ntins pe mai multe linii fizice, care se numetereunire explicit a liniilor.
s = 'Acesta este un ir \ care continu pe a doua linie.' print(s)

Se obine rezultatul:
Acesta este un ir care continu pe a doua linie.

Similar,
print\ (i)

este la fel ca

print(i)

Exist i reunire implicit a liniilor, conform unei prezumii care elimin nevoia de backslash. Este cazul n care linia logic folosete paranteze rotunde, paranteze drepte sau acolade. Le vei vedea n aciune cnd vom scrie programe folosind liste n capitolele finale. Indentarea Spaiul alb este important n Python. De fapt, spaiul alb la nceputul liniei este important. Acesta se numete indentare. Spaiul alb (spaii i taburi) de la nceputul liniei logice este folosit pentru a determina nivelul de indentare al liniei logice, care la rndul lui este folosit pentru a determina gruparea declaraiilor. Asta nseamn c declaraiile care merg mpreun trebuie s aib aceeai indentare. Fiecare astfel de set de declaraii se numete bloc. Vom vedea exemple despre importana blocurilor n capitolele urmtoare. Un lucru demn de reinut este c indentarea greit poate produce erori. De exemplu:
i = 5 print('Valoarea este ', i) # Eroare! Observai un spaiu la nceputul liniei. print('Repet, valoarea este ', i)

Cnd rulai asta, obinei urmtoarea eroare:


File "whitespace.py", line 4 print('Valoarea este ', i) # Eroare! Observai un singur spaiu la nceputul liniei. ^ IndentationError: unexpected indent

Observai c exist un spaiu la nceputul liniei a doua. Eroarea indicat de Python ne spune c sintaxa este greit, adic programul nu a fost scris corespunztor. Asta nseamn c nu poi ncepe n mod arbitrar noi blocuri de declaraii cu excepia blocului principal[9] implicit pe care l-ai folosit tot timpul. Cazurile n care putei folosi un nou bloc de declaraii vor fi detaliate n capitolele finale, cum ar fi capitolul despre controlul execuiei. Cum se indenteaz

Nu folosii un amestec de SPACE i TAB fiindc programele nu vor lucra corect pe toate platformele. V recomand clduros s folosii un singur TAB sau patru spaii pentru fiecare nivel de indentare. Alegei oricare din aceste stiluri de indentare. i mai important, alegei un stil i folosii-l n mod consistent i exclusiv. Not pentru programatorii n limbaje cu tipuri statice Python va folosi mereu indentarea pentru blocuri i niciodat acolade. Rulai from __future__ import braces pentru a afla mai multe detalii. Rezumat Acum c am trecut prin multe detalii eseniale, putem continua cu lucruri mai interesante cum ar fi declaraii pentru controlul execuiei. Asigurai-v c ai neles ce ai nvatat n acest capitol.

Python ro:Operatori i expresii


Contents

1 Introducere 2 Operatori 2.1 Prescurtare pentru operaii matematice i atribuiri 3 Ordinea de evaluare 4 Schimbarea ordinii de evaluare 5 Asociativitatea 6 Expresii 7 Rezumat

Introducere Majoritatea declaraiilor (linii logice) pe care le scriei conin expresii. Un exemplu de expresie simpl este 2 + 3. O expresie poate fi descompus n operatori i operanzi. Operatorii sunt functionaliti care execut ceva i pot fi reprezentai prin simboluri precum+ sau prin cuvinte cheie speciale. Operatorii au nevoie de nite date asupra crora s opereze, numite operanzi. n acest caz, 2 i 3 sunt operanzii. Operatori Vom arunca o privire rapid asupra operatorilor i a folosirii lor: Reinei c putei evalua expresiile date n exemple folosind interactiv interpretorul. De exemplu, pentru a testa expresia 2 + 3, folosind interactiv interpretorul Python:
>>> 2 + 3 5 >>> 3 * 5 15

>>>
EXPLICAIE

OPERATOR NUME

EXEMPLE

Plus

adun dou obiecte

3 + 5 fac 8 'a' + 'b' fac 'ab'.

Minus

fie face un numr s fie negativ fie d diferena ntre dou numere

-5.2 face negativ numrul 5.2 50 - 24 fac 26.

Inmulire

d produsul a dou numere sau repetarea unui ir de numrul specificat de ori

2 * 3 fac 6 'la' * 3 d 'lalala'. 3 ** 4 d 81 (adic 3 * 3 * 3 * 3)

**

Putere

d x la puterea y

mprire

mparte x la y 4 / 3 d 1.3333333333333333.

//

mprire ntreag

d partea ntreag a ctului 4 // 3 fac 1.

Modulo

d restul mpririi

8% 3 fac 2 -25.5% 2.25 fac 1.5.

<<

Translaie la stnga

Translateaza biii unui numr la stnga cu numrul specificat de bii. (Orice numr este 2 << 2 da 8 reprezentat n memorie sub 2 este reprezentat prin 10 n bii. forma de bii cifre binare Prin translaie la stnga cu doi bii 0 i 1) se obine1000 ceea ce reprezint numrul 8. Translateaza biii numrului la dreapta cu numrul specificat de bii. 11 >> 1 d 5 11 este reprezentat n bii prin 1011care translatat la dreapta cu un bit d101 ceea ce reprezint numrul 5.

>>

Translaie la dreapta

&

AND

I binar ntre numere 5 & 3 da 1.

OR

SAU binar ntre numere 5 | 3 d 7

XOR

SAU exclusiv binar ntre numere 5 ^ 3 fac 6

Complement complementul lui x este binar (x+1) ~5 d -6. Valoarea de adevr a propoziiei x este mai mic dect y. Toi operatorii de comparaie iau valorile logice True sau False. Observai c aceste nume ncep cu majuscul.

<

Mai mic (dect)

5 < 3 d False 3 < 5 d True. Comparaiile pot fi nlnuite arbitrar: 3 < 5 < 7 d True.

>

Mai mare (dect)

5 > 3 d True. Dac ambii operanzi sunt numere, acetia sunt convertii Valoarea de adevr a nti la un tip comun. n caz contrar propoziiei x este mai mare operaia ar avea mereu dect y. valoarea False. Valoarea de adevr a propoziiei x este mai mic sau cel mult egal cu y. x = 3; y = 6; x <= y d True.

<=

Mai mic sau egal (cu)

>=

Mai mare sau egal (cu)

Valoarea de adevr a propoziiei x este mai mare sau cel puin egal cu y. x = 4; y = 3; x >= 3 da True.

==

Egal (cu)

Verific dac dou numere sunt egale

x = 2; y = 2; x == y d True. x = 'str'; y = 'stR'; x == y d False. x = 'str'; y = 'str'; x == y d True.

!=

Diferit (de)

Verific dac dou numere sunt diferite x = 2; y = 3; x!= y d True.

not

NU logic

dac x este True, dFalse. Dac x esteFalse, d True. x and y d False dac x este False, altfel d valoarea lui y

x = True; not x d False. x = False; y = True; x and y d Falsentruct x este False. n acest caz, Python nu va evalua pe y

and

I logic

fiindc tie c partea stng a expresiei and esteFalse ceea ce d ntregii expresii valoarea False indiferent de celelalte valori. Acest fapt se numete evaluare n circuit scurt. or SAU logic dac x este True, dTrue, altfel d valoarea lui y x = True; y = False; x or y d True. i aici se aplic evaluarea n circuit scurt.

Operatori i folosirea lor


PRESCURTARE PENTRU OPERAII MATEMATICE I ATRIBUIRI

Este uzual s faci o prelucrare matematic a unei variabile i s pstrezi apoi rezultatul tot n ea; de aceea exist o prescurtare pentru acest fel de expresii: n loc de:
a = 2; a = a * 3

putei scrie:
a = 2; a *= 3

Observai c var = var operaie expresie devine var operaie= expresie. Ordinea de evaluare Daca avei o expresie precum 2 + 3 * 4, se va evalua nti operaia de adunare sau cea de nmulire? Matematica de liceu ne nva c multiplicarea ar trebui fcut nti. Asta nseamn c operatorul de nmulire are preceden mai mare dect operatorul de adunare. Tabelul urmtor d precedena operatorilor n Python, de la cea mai mic preceden (cea mai slab legtur) pn la cea mai mare preceden (cea mai strns legtur). Asta nseamn c ntro expresie dat, Python va evalua nti operatorii i expresiile cele mai de jos n tabel naintea celor mai de sus. Urmtorul tabel, extras din manualul de referine Python, este dat de dragul completitudinii. Este de departe mai bine s folosim paranteze pentru a grupa operatorii i operanzii n mod adecvat pentru a specifica precedena. Astfel programul devine mai lizibil. Pentru detalii v rog s urmrii mai jos Schimbarea ordinii de evaluare.
OPERATOR DESCRIERE

lambda

Expresie lambda

or

SAU logic

and I logic not x NU logic

in, not in

Teste de apartenen

is, is not Teste de identitate <, <=, >, >=,!=, == Comparaii

SAU binar

SAU-exclusiv binar

& I binar <<, >> Translaii

+, Adunare i scdere *, /, //, % nmulire, mprire, mprire ntreag, modulo

+x, -x

Pozitiv, negativ

~x

NU binar

**

Exponeniere

x.atribut

Referin la atribut

x[index] Referin la element x[index1:index2] Feliere

f(argumente )

Apel la funcie

(expresii, )

Legtura sau afiarea unui cuplu

[expresii, ...]

Afiarea unei liste

{cheie:date, } Precedena operatorilor

Afiarea unui dicionar

Operatorii pe care nu i-am ntlnit pn acum vor fi descrii n capitolele viitoare. Operatorii cu aceeai preceden sunt listai n acelai rnd n tabelul anterior. De exemplu, + i au aceeai preceden. Schimbarea ordinii de evaluare Pentru a face expresiile mai lizibile, putem folosi paranteze. De exemplu, 2 + (3 * 4) este n mod clar mai uor de neles dect 2 + 3 * 4 care necesit cunoaterea precedenei operatorilor. Ca i orice altceva, parantezele trebuie folosite cu discernmnt (nu exagerai) i fr redundan (ca n 2 + (3 + 4)). Exist un avantaj suplimentar n folosirea parantezelor ne ajut s schimbm ordinea de evaluare. De exemplu, dac vrei s fie evaluat adunarea naintea nmulirii ntro expresie, trebuie s o scriei (2 + 3) * 4. Asociativitatea Operatorii sunt de obicei asociativi de la stnga la dreapta, adic operatorii cu aceeai preceden sunt evaluai de la stnga la dreapta. De exemplu, expresia 2 + 3 + 4 este evaluata ca (2 + 3) + 4. Civa operatori, precum atribuirea sunt asociativi de la dreapta la stnga astfel espresia a = b = c este evaluat caa = (b = c). Expresii Exemplu:

#!/usr/bin/python # Fiier: expression.py lungime = 5 lime = 2 aria = lungime * lime print('Aria este', aria) print('Perimetrul este', 2 * (lungime + lime))

Rezultat:
$ python expression.py Aria este 10 Perimetrul este 14

Cum funcioneaz: Lungimea i limea dreptunghiului sunt stocate n variabile cu numele respective. Le folosim pentru a calcula aria i perimetrul dreptunghiului cu ajutorul expresiilor. Stocm rezultatul expresiei lungime * lime n variabila aria i o afim folosind funcia print. n al doilea caz, folosim direct valoarea expresiei 2 * (lungime + lime) n funcia print. De asemenea, observai cum Python cosmetizeaz tiprirea rezultatului. Dei noi n-am specificat un spaiu ntre 'Aria este' i variabila aria, Python o face pentru noi ca s obinem o prezentare mai clar i astfel programul este mult mai lizibil (fiindc nu mai trebuie s ne ngrijim de spaierea irurilor folosite pentru afiare). Acesta este un exemplu despre cum face Python viaa programatorului mai uoar. Rezumat Am nvat ce sunt operatorii, operanzii i expresiile acestea sunt componentele de baz ale oricarui program. n continuare vom vedea cum se folosesc n declaraii.

Python ro:Controlul execuiei


Contents

1 Introducere 2 Declaraia if 3 Declaraia while 4 Bucla for 5 Declaraia break 5.1 Poezia lui Swaroop despre Python 6 Declaraia continue 7 Rezumat

Introducere n programele pe care le-am vzut pn acum erau o serie de declaraii i Python le executa credincios n aceeai ordine. Dar dac am fi vrut s schimbam fluxul sau modul lui de lucru? De exemplu, vrei ca programul s ia nite decizii i s fac procesri diferite n diferite situaii, precum a tipri Bun ziua sau Bun seara n funcie de ora la care se execut programul? Cum poate ai ghicit, asta se poate face cu declaraii de control al execuiei. Exist trei declaraii de control al execuiei n Python if, for i while. Declaraia if Declaraia if este folosit pentru a testa o condiie i, dac aceasta este adevrat, s ruleze un bloc de declaraii (numit blocul if), iar n caz contrar s ruleze alt bloc de declaraii (blocul else). Clauza else este optional. Exemplu:
#!/usr/bin/python # Fiier: if.py numr = 23 ghici = int(input('Introducei un ntreg: ')) if ghici == numr: print('Felicitri, ai ghicit,') # Noul bloc ncepe aici print('(dar nu ctigai niciun premiu!)') # Noul bloc se ncheie aici elif ghici < numr: print('Nu, e un pic mai mare.') # Alt bloc # Poti face ce vrei ntr-un bloc ... else: print('Nu, e un pic mai mic.') # Ca s ajungei aici e sigur ca ghici > numr print('Gata') # Aceasta ultim declaraie este executat ntotdeauna, dup declaraia if

Rezultat:
$ python if.py Introducei un ntreg: 50 Nu, e un pic mai mic. Gata

$ python if.py

Introducei un ntreg: 22 Nu, e un pic mai mare. Gata

$ python if.py Introducei un ntreg: 23 Felicitri, ai ghicit, dar nu ctigai niciun premiu! Gata

Cum funcioneaz: n acest program prelum de la utilizator ncercri de a ghici numrul i verificm dac este numrul memorat. Setm variabila numr la ce valoare vrem, s zicem 23. Apoi prelum numrul ncercat de utilizator folosind funcia input(). Funciile sunt nite poriuni de program reutilizabile. Vom afla mai multe despre ele n capitolul urmtor. Furnizm un ir funciei implicite input() care l tiprete pe ecran i ateapt introducerea de informaie de la utilizator. ndat ce introducem ceva (ENTER rom. a intra/introduce) i apsm tasta ENTER, funcia input() d ca rezultat ceea ce am introdus, sub form de ir. Convertim acest ir ntrun ntreg folosind declaraia int i stocm valoarea n variabilaghici. De fapt int este o clas, dar ce trebuie s tii n acest moment este c l folosii pentru a converti un ir ntr-un ntreg (presupunnd c irul conine un ntreg valid n text). n continuare comparm alegerea utilizatorului cu numrul stabilit de noi. Dac acestea sunt egale, tiprim un mesaj de succes. Observai c folosim nivele de indentare pentru a-i spune Pythonului crui bloc aparine fiecare declaraie. Iat de ce este indentarea atat de important n Python. Sper c v-ai ataat de regula indentrii consistente. Este aa? Observai cum declaraia if conine semnul dou puncte la sfrit aa i spunem Pythonului c urmeaz un bloc de declaraii. Mai departe, testm dac numrul furnizat de utilizator este mai mic dect numrul i, dac este aa, informm utilizatorul c trebuie s inteasc mai sus de att. Ce am folosit aici este clauza elif care de fapt combin dou declaraii if else-if else ntr-o singur declaraie if-elif-else. Asta face programul mai uor i reduce numrul de indentri necesar.

i clauzele elif i else trebuie s aib la sfritul liniei logice semnul dou puncte dup care poate urma blocul lor de declaraii (cu indentarea adecvat, desigur). Putei pune o alt declaraie if n interiorul blocului if al declaraiei if s.a.m.d. n acest caz declaraiile if se numesc imbricate (engl. nested). Clauzele elif i else sunt opionale. O declaraie if minimal este:
if True: print('Da, e adevarat.')

Dup ce Python a terminat execuia ntregii declaraii if inclusiv clauzele elif i else, el trece la urmtoarea declaraie din blocul care conine declaraia if. n acest caz este vorba de blocul main (rom. principal), unde ncepe ntotdeauna execuia programului, iar instruciunea urmtoare este declaraia print('Gata'). Dup aceasta, Python vede sfritul programului i ncheie. Dei acesta este un program foarte simplu, am indicat o mulime de lucruri care trebuie observate. Toate acestea sunt destul de directe (i simple pentru cei care au cunotine de C/C++) i iniial necesit s devenii constieni de ele, dar apoi vor deveni uzuale i v vor prea naturale. Not pentru programatorii n C/C++ Nu exist declaraia switch n Python. Putei utiliza declaraia if..elif..else pentru a face acelai lucru (i n unele cazuri, putei folosi o structur de date pentru a rezolva repede). Declaraia while Declaraia while ne permite s executm repetat un bloc de declaraii att timp ct o condiie rmne adevrat. O declaraie while este un exemplu de instruciune de ciclare. Poate avea i clauza else. Exemplu:
#!/usr/bin/python # Fiier: while.py numr = 23 ciclu = True while ciclu: ghici = int(input('Introducei un ntreg: ')) if ghici == numr: print('Felicitri, ai ghicit!') ciclu = False # asta face ciclul s se ntrerup elif ghici < numr: print('Nu, este puin mai mare.') else: print('Nu, este puin mai mic..') else: print('Bucla s-a ncheiat.') # Aici putei face ce prelucrri vrei print('Gata')

Rezultat:
$ python while.py Introducei un ntreg: 50 Nu, este puin mai mic. Introducei un ntreg: 22 Nu, este puin mai mare Introducei un ntreg: 23 Felicitri, ai ghicit. Bucla s-a ncheiat. Gata

Cum funcioneaz: n acest program jucm tot jocul cu ghicirea numrului, dar avantajul este ca utilizatorul poate continua ncercrile pn cnd ghicete nu trebuie s ruleze programul de fiecare dat, cum am facut n programul precedent. Ceea ce este chiar o demostraie de declaraie while. Deplasm declaraiile input i if n interiorul buclei while i iniializm variabila ciclu cu Truenaintea buclei. La nceput testm dac variabila ciclu este True i apoi continum cu executarea blocului while. Dup ce blocul a fost executat, condiia este evaluat din nou i, n acest caz, condiia este variabila ciclu. Dac este True, executm blocul while din nou, altfel verificm dac exist o clauz else ca s-o executm. Blocul else este executat atunci cand condiia de ciclare devine False asta poate fi chiar i prima dat cnd se testeaz condiia. Dac exista un bloc else la bucla while, ea va fi ntotdeauna executat, dac nu se iese forat din bucl cu o declaraie break. Valorile True i False sunt numite booleene i pot fi considerate a fi echivalente cu valorile1 i respectiv 0. Not pentru programatorii n C/C++ Reinei c poate exista o clauz else la bucla while. Bucla for Declaraia for..in este o declaraie de ciclare care itereaz elementele unei secvene de obiecte. Vom afla mai multe despre secvene n capitolele urmtoare. Ce trebuie tiut acum este c o

secven este pur i simplu o colecie ordonat de elemente. Exemplu:


#!/usr/bin/python # Fiier: for.py for i in range(1, 5): print(i) else: print('Bucla s-a terminat')

Rezultat:
$ python for.py 1 2 3 4 Bucla s-a terminat

Cum funcioneaz: n acest program, tiprim o secven de numere. Generm secvena cu ajutorul funciei predefinite range. Noi dm funciei range dou numere i ea ne d secvena de numere ncepnd cu primul numr i pn la cel de-al doilea. De exemplu, range(1,5) nseamn secvena [1, 2, 3, 4]. Implicit, range are pasul 1. Dac i dm i un al treilea numr, range acela devine pasul secvenei. De exemplu range(1,5,2) d [1,3]. Reinei c gama de numere (engl. range) se extinde pn la al doilea numr, dar nu l i include. Aadar bucla for itereaz peste acesta gam for i in range(1,5) este echivalent cu for i in [1, 2, 3, 4] ceea ce este ca i cum s-ar atribui fiecare obiect din secven lui i, pe rnd, i executarea blocului de declaraii pentru fiecare valoare a lui i. n acest caz, nu facem altceva dect s tiprim valoarea obiectului. Amintii-v c clauza else este opional. Cnd este inclus, este executat ntotdeauna o dat, dup ncheierea buclei for, cu excepia cazului n care se ntlnete o declaraiebreak. De reinut c bucla for..in funcioneaz pentru orice secven. n acest caz avem doar o list de numere, generat cu funcia predefinit range, dar n general, putem folosi orice fel de secven de orice fel de obiecte. Not pentru programatorii n C/C++/Java/C#

n Python bucla for este radical diferit de bucla for din C/C++. Programatorii C# vor reine c bucla for din Python este similar cu bucla foreach din C#. Programatorii Java s observe c acelai lucru este similar cu for (int i: IntArray) n Java 1.5. n C/C++, dac vrei s scrii for (int i = 0; i < 5; i++), atunci n Python scrii doar for i in range(0,5). Aa cum vedei, n Python bucla for este mai simpl, mai expresiv i mai puin predispus la erori. Declaraia break Declaraia break este folosit pentru a ntrerupe (engl. break) executarea unei declaraii de ciclare, chiar i dac condiia testat nu a devenit nc False sau secvena nu a fost parcurs complet. O not important este c dac se ntrerupe o bucla for sau while, nici clauza else nu va fi executat. Exemplu:
#!/usr/bin/python # Fiier: break.py while True: s = (input('Introducei ceva:')) if s == 'quit': break print('Lungimea irului introdus este', len(s)) print('Gata')

Rezultat:
$ python break.py Introducei ceva: Programarea e mito Lungimea irului introdus este 15 Introducei ceva: Cnd treaba e facut Lungimea irului introdus este 20 Introducei ceva: Dac vrei s te i distrezi: Lungimea irului introdus este 27 Introducei ceva: folosete Python!

Lungimea irului introdus este 17 Introducei ceva: quit Gata

Cum funcioneaz: n acest program, prelum datele de intrare n mod repetat de la utilizator i tiprim lungimea fiecrui ir introdus. Prevedem i o condiie special pentru oprirea programului, prin cutarea cuvntului 'quit'. Oprim programul prin ntreruperea buclei i ajungerea la sfritul blocului de declaraii. Lungimea irului de intrare poate fi gsit folosind funcia predefinit len. Reinei c declaraia break poate fi folosit i cu declaraia for.
POEZIA LUI SWAROOP DESPRE PYTHON

Ce am folosit aici drept intrare (de la utilizator) este un mini poem scris de mine, numitSwaroops Poetic Python (n limba englez):
Programming is fun When the work is done if you wanna make your work also fun: use Python!

Declaraia continue Declaraia continue se folosete pentru a spune lui Python s treac la urmtoarea iteraie fr s execute instruciunile rmase din blocul declaraiei de ciclare. Exemplu:
#!/usr/bin/python # Fiier: continue.py while True: s = input('Introducei ceva: ') if s == 'quit': break if len(s) < 3: print('Prea puin') continue print('irul introdus are lungime suficient') # Facei alte procesri aici...

Rezultat:
$ python test.py Introducei ceva: a Prea puin

Introducei ceva: 12 Prea puin Introducei ceva: abc irul introdus are lungime suficient Introducei ceva: quit

Cum funcioneaz: n acest program acceptm date de la utilizator, dar le procesm doar dac au cel puin 3 caractere lungime. Aadar, folosim funcia len pentru a obine lungimea i, dac aceasta este mai mic dect 3, srim peste ce a mai rmas din iteraia curent folosind declaraiacontinue. n caz contrar, restul declaraiilor din bucl sunt executate i putem s facem orice fel de procesare n zona unde este acel comentariu. Retinei c declaraia continue funcioneaz i cu bucla for. Rezumat Am vzut cum se folosesc cele trei instruciuni de control al execuiei if, while i formpreun cu asociatele lor, declaraiile break i continue. Acestea sunt unele dintre cele mai utilizate pri din Python i de aceea este esenial s te obinuieti cu ele. n continuare vom nva s construim i s folosim funcii.

Python ro:Funcii
Contents

1 Introducere 2 Parametrii funciilor 3 Variabile locale 4 Folosirea declaraiei global 5 Folosirea declaraiei nonlocal 6 Valori implicite ale argumentelor 7 Argumente cuvnt cheie 8 Parametri VarArgs 9 Parametri exclusiv cuvnt cheie 10 Declaraia return 11 DocStrings 12 Adnotri 13 Rezumat

Introducere

Funciile sunt poriuni de program reutilizabile. Ele v permit s dai nume unui bloc de declaraii i putei rula acel bloc de declaraii n program de cte ori vrei. Asta se numeteapel al funciei. Noi am folosit deja multe funcii predefinite precum len i range. Conceptul de funcie este probabil cel mai important bloc constructiv al oricrui program nonbanal (n orice limbaj de programare), deci vom explora diverse aspecte ale funciilor n acest capitol. Funciile sunt definite folosind cuvntul cheie def. Acesta este urmat de un numeidentificator pentru funcie urmat de o pereche de paranteze care pot include nite nume de variabile. n continuare este plasat blocul de declaraii care compun funcia. Un exemplu va arta ct este de simplu: Exemplu:
#!/usr/bin/python # Fiier: function1.py def sayHello(): print('Hello World!') # blocul funciei # Sfritul funciei sayHello() # apel la funcia sayHello() sayHello() # din nou apel la funcia sayHello()

Rezultat:
$ python function1.py Hello World! Hello World!

Cum funcioneaz: Definim o funcie numit sayHello folosind sintaxa explicat mai sus. Aceasta funcie nu primete parametri i deci nu sunt declarate variabile n paranteze. Parametrii pentru funcie sunt doar nite modaliti de a-i transmite funciei diferite valori sau/i de a extrage valorile corespunztoare. Observai c putem apela aceeai funcie de dou ori, ceea ce nseamn c nu mai trebuie s scriem aceeai poriune de cod din nou. Parametrii funciilor O funcie poate accepta parametri, care sunt valori furnizate funciei pentru ca aceasta s poat face ceva cu aceste valori. Aceti parametri sunt ca variabilele numai c valorile acestor

variabile sunt definite n momentul apelului funciei i deja le sunt atribuite valori la momentul executrii blocului funciei. Parametrii sunt specificai ntr-o pereche de paranteze n definiia funciei, separate prin virgule. Cnd apelm funcia, furnizm aceste valori ntr-un fel sau altul. Observai terminologia folosit numele date n funcie se numesc parametri n timp ce valorile pe care le furnizm n apelul funciei se numesc argumente. Exemplu:
#!/usr/bin/python # Fiier: func_param.py def printMax(a, b): if a > b: print(a, 'este maximum') elif a == b: print(a, 'este egal cu', b) else: print(b, 'este maximum') printMax(3, 4) # argumente date prin literali x = 5 y = 7 printMax(x, y) # argumente date prin variabile

Rezultat:
$ python func_param.py 4 este maximum 7 este maximum

Cum funcioneaz: Aici definim o funcie numit printMax care primete doi parametri numii a i b. Gsim cel mai mare numr dintre ele folosind o simpla declaraie if..else i tiprim pe ecran cel mai mare numr. n primul apel al funciei printMax, furnizm argumentele n forma literal. n al doilea apel dm funciei valorile parametrilor prin intermediul variabilelor. printMax(x, y) face ca valoarea variabilei x s fie atribuit parametrului a i valoarea variabilei y s fie atribuit parametrului b. Funcia printMax lucreaz la fel n ambele cazuri. Variabile locale

Cnd se declar variabile n interiorul definiiei funciei, acestea nu au nici un fel de legtur cu alte variabile din afara definiiei funciei, nici chiar dac ar avea acelai nume, de aceea se numesc variabile locale funciei. Acesta este domeniul variabilei. Toate variabilele au ca domeniu blocul n care sunt declarate, ncepnd cu punctul n care a fost definit numele ei. Exemplu:
#!/usr/bin/python # Fiier: func_local.py x = 50 def func(x): print('x este', x) x = 2 print('Am schimbat x local n ', x) func(x) print('x este tot ', x)

Rezultat:
$ python func_local.py x este 50 Am schimbat x local n 2 x este tot 50

Cum funcioneaz: n funcie, prima dat cnd folosim valoarea numelui x, Python folosete valoarea parametrului declarat n funcie. n continuare atribuim valoarea 2 lui x. Numele x este local funciei noastre. Prin urmare, cnd schimbm valoarea lui x n funcie, x definit n blocul principal rmne neafectat. n ultimul apel al funciei print, afim valoarea lui x din blocul principal ca s confirmm c a rmas neafectat. Folosirea declaraiei global Dac vrei s atribuii o valoare unui nume definit la nivelul cel mai nalt al programului (adic nu n interiorul domeniului funciei sau clasei), va trebui s-i spunei lui Python c acel nume nu este local ci global. Obinem asta folosind declaraia global. Este imposibil ca n interiorul unei funcii s atribui o valoare unei variabile definite n afara funciei fr declaraia global.

Putei folosi valorile definite n afara funciilor (presupunnd c nu exist o variabil cu acelai nume definit n blocul funciei). Totui, acest fapt nu este ncurajat i trebuie evitat ntruct devine neclar cititorului unde este definiia acelei variabile. Folosind declaraiaglobal marcm foarte clar c variabila este definit n cel mai exterior bloc. Exemplu:
#!/usr/bin/python # Fiier: func_global.py x = 50 def func(): global x print('x is', x) x = 2 print('Am schimbat x global n ', x) func() print('Valoarea lui x este', x)

Rezultat:
$ python func_global.py x este 50 Am schimbat x global n 2 Valoarea lui x este 2

Cum funcioneaz: Declaraia global este folosit pentru a declara c x este o variabil global de aceea, cnd atribuim o valoare lui x n interiorul funciei, acea schimbare se reflect cnd folosim valoarea lui x n blocul principal. Putei specifica mai multe variabile globale folosind declaraia global. De exemplu, global x, y, z. Folosirea declaraiei nonlocal Am nvat s accesm variabile n domeniul local i global. Mai exist un domeniu specific funciilor, numit nonlocal i care se afl ntre cele dou. Domeniile nonlocal se observ cnd definii funcii n interiorul funciilor. ntruct totul n Python este cod executabil, se pot defini funcii oriunde. S lum un exemplu:

#!/usr/bin/python # Fiier: func_nonlocal.py def func_outer(): x = 2 print('x este', x) def func_inner(): nonlocal x x = 5 func_inner() print('x local a devenit ', x) func_outer()

Rezultat:
$ python func_nonlocal.py x este 2 x local a devenit 5

Cum funcioneaz: Cnd ne aflm n interiorul unei funcii func_inner, x definit n prima linie a funcieifunc_outer este undeva ntre global i local. Declarm c folosim acest x cu declaraianonlocal x i astfel obinem acces la acea variabil. ncercai s schimbai nonlocal x cu global x i s eliminai complet declaraia, ca s vedei ce diferene de comportament sunt n aceste cazuri. Valori implicite ale argumentelor Pentru unele funcii, poate vrei s facei unii parametri opionali i s folosii valori implicite n cazul n care utilizatorul nu furnizeaz o valoare pentru parametrul respectiv. Asta se face cu ajutorul valorilor implicite ale parametrilor. Putei specifica valorile implicite ale argumentelor n definiia funciei, punnd operatorul de atribuire (=) urmat de valoarea implicit. Observai c valoarea implicit a argumentului trebuie s fie o constant. Mai precis, trebuie s fie imuabil acest fapt va fi explicat n detaliu n capitolele urmtoare. Pentru moment reinei doar att. Exemplu:
#!/usr/bin/python # Fiier: func_default.py def say(mesaj, ori = 1): print(mesaj * ori)

say('Hello') say('World', 5)

Rezultat:
$ python func_default.py Hello WorldWorldWorldWorldWorld

Cum funcioneaz: Funcia numit say este folosit pentru a tipri pe ecran un ir de attea ori ct se specific. Dac nu furnizm acea valoare, atunci va fi folosit valoarea implicit, 1. Obinem aceasta punnd valoarea implicit 1 a parametrului ori. La prima folosire a funciei say, dm numai irul i ea l tiprete o dat. n a doua folosire dm funciei say i irul i un argument 5 ceea ce spune c vrem s fie tiprit irul de 5 ori. Important Numai parametrii de la sfritul listei de parametri pot avea valori implicite deci nu putei avea un parametru cu valoare implicit naintea altuia fr valoare implicit n lista de parametri a funciei. Motivul este c valorile sunt atribuite parametrilor prin poziie. De exemplu, def func(a, b=5) este valid, dar def func(a=5, b) este invalid. Argumente cuvnt cheie Dac avei funcii cu muli parametri i vrei s specificai numai pe unii, atunci putei s dai valori parametrilor prin numele lor acest mod de specificare se numete prin argumente cuvnt cheie folosim cuvntul cheie (engl. keyword) n locul poziiei (pe care am folosit-o pn acum) pentru a specifica argumente funciei. Exist dou avantaje unu, folosirea funciei este mai uoar, ntruct nu trebuie s ne preocupm de ordinea parametrilor. Doi, putem da valori numai unor parametri selectai, cu condiia ca toi ceilali sa aib n definiia funciei valori implicite. Exemplu:
#!/usr/bin/python # Fiier: func_key.py def func(a, b=5, c=10):

print('a este', a, 'i b este', b, 'i c este', c) func(3, 7) func(25, c=24) func(c=50, a=100)

Rezultat:
$ python func_key.py a este 3 i b este 7 i c este 10 a este 25 i b este 5 i c este 24 a este 100 i b este 5 i c este 50

Cum funcioneaz: Funcia numit func are un parametru fr valoare implicit, urmat de doi parametri cu valori implicite. n primul apel, func(3, 7), parametrul a primete valoarea 3, parametrul b primete valoarea 7, iar c valoarea implicit, 10. n al doilea apel, func(25, c=24), variabila a ia valoarea 25 datorit poziiei argumentului. Pe urm, parametrul c ia valoarea 24 prin nume argument cuvnt cheie. Variabila b ia valoarea implicit, 5. n al treilea apel, func(c=50, a=100), folosim numai tehnica nou, a cuvintelor cheie. Observai, specificm valoarea parametrului c naintea parametrului a dei a este definit naintea variabilei c n definiia funciei. Parametri VarArgs TODO S scriu despre asta ntr-un capitol urmtor, fiindc nu am vorbit nc despre liste i dicionare? Uneori ai putea dori s definii o funcie care s ia orice numr de parametri, asta se poate face folosind asteriscul:
#!/usr/bin/python # Fiier: total.py def total(iniial=5, *numere, **keywords): numrtor = iniial for numr in numere: numrtor += numr for cheie in keywords:

numrtor += keywords[cheie] return numrtor print(total(10, 1, 2, 3, legume=50, fructe=100))

Rezultat:
$ python total.py 166

Cum funcioneaz: Cnd declarm un parametru cu asterisc precum *parametri, toi parametrii poziionali de la acel punct ncolo sunt colectai ntro list numit parametri. Similar, cnd declarm un parametru cu dou asteriscuri, precum **parametri, toate argumentele cuvnt cheie de la acel punct ncolo sunt colectate ntr-un dicionar numit parametri. Vom explora listele i dicionarele ntrun capitol urmtor. Parametri exclusiv cuvnt cheie Dac vrem s specificm anumii parametri cuvnt cheie pentru a fi disponibili numai n forma cuvnt cheie i niciodat ca parametri poziionali, acetia pot fi declarai dup un parametru cu asterisc:
#!/usr/bin/python # Fiier: keyword_only.py def total(iniial=5, *numere, legume): numrtor = iniial for numr in numere: numrtor += numr numrtor += legume return numrtor print(total(10, 1, 2, 3, legume=50)) print(total(10, 1, 2, 3)) # Ridic o eroare pentru c nu am furnizat o valoare implicit pentru 'legume'

Rezultat:
$ python keyword_only.py 66 Traceback (most recent call last): File "test.py", line 12, in <module> print(total(10, 1, 2, 3))

TypeError: total() needs keyword-only argument legume

Cum funcioneaz: Declararea de parametri dup un parametru cu asterisc (engl. starred parameter) produce argumente exclusiv cuvnt cheie. Dac acestea nu sunt definite cu valori implicite, apelurile funciei vor ridica o eroare dac nu se furnizeaz argumentul cuvnt cheie, aa cum s-a vzut mai sus. Dac vrei s avei parametri exclusiv cuvnt cheie, dar nu avei nevoie de nici un parametru cu asterisc, folosii un asterisc izolat, ca n exemplul: def total(iniial=5, *, legume). Declaraia return Declaraia return este folosit pentru a ne ntoarce dintr-o funcie (deci a evada din ea engl. break out). Opional putem ntoarce o valoare la fel de bine. Exemplu:
#!/usr/bin/python # Fiier: func_return.py def maximum(x, y): if x > y: return x else: return y print(maximum(2, 3))

Rezultat:
$ python func_return.py 3

Cum funcioneaz: Funcia maximum ntoarce parametrul cel mai mare furnizat funciei. Ea folosete o declaraie simpl if..else pentru a gsi numrul cel mai mare i apoi ntoarce (engl. return) acea valoare. Observai c declaraia return fr o valoare este echivalent cu return None. None este un tip special n Python care reprezint nimicul. De exemplu, este folosit pentru a indica faptul c o variabil nu are nici o valoare, deci are valoarea None.

Orice funcie, n mod implicit, conine o declaraie return None la sfritul blocului de declaraii, cu excepia cazului n care i scriei o alt declaraie return. Putei vedea asta rulnd print o_funcie_oarecare() n care nu este dat o declaraie return precum:
def o_functie_oarecare(): pass

Declaraia pass este folosit n Python pentru a indica un bloc de declaraii gol. Not Exist o funcie predefinit numit max care implementeaz aceast funcionalitate de a gsi maximul, deci folosirea aceste funcii este posibil oricand. DocStrings Python are o facilitate drgu numit documentation strings, numit de obicei pe numele scurt docstrings. DocStrings (rom. iruri de documentaie, sg. docstring) sunt o unealt important pentru c v ajut s documentai programele mai bine i le face mai uor de neles. Uimitor, putem chiar s extragem irurile de documentare ale, s zicem, unei funcii chiar n timp ce programul ruleaz! Exemplu:
#!/usr/bin/python # Fiier: func_doc.py def printMax(x, y): '''Tiprete pe ecran cel mai mare din dou numere. Cele dou numere trebuie s fie ntregi.''' x = int(x) # convertete n integer, dac este posibil y = int(y) if x > y: print(x, 'este maximum') else: print(y, 'este maximum') print(printMax.__doc__) printMax(3, 5)

Rezultat:
$ python func_doc.py Tiprete pe ecran cel mai mare din dou numere.

Cele dou numere trebuie s fie ntregi.

5 este maximum

Cum funcioneaz: Un ir pe prima linie logic a funciei devine docstring pentru acea funcie. De retinut c DocStrings se aplic i la module i clase, despre care vom nva n capitolele respective. Convenia urmat pentru un docstring este: un ir multilinie n care prima linie ncepe cu majuscul i se ncheie cu punct. Apoi linia a doua este goal i urmat de o explicaie mai detaliat ncepand cu linia a treia. V sftuim cu cldur s urmai aceasta convenie pentru toate docstringurile tuturor funciilor nebanale pe care le scriei. Putem accesa docstringul funciei printMax folosind atributul __doc__ (observai dublu underscore) al funciei. Amintii-v c Python trateaz totul ca obiect, inclusiv funciile. Vom nva mai mult despre obiecte n capitolul despre clase. Daca ai folosit help() n Python, ai vzut deja cum se folosete docstring! Ceea ce face ea este c extrage atributul __doc__ al funciei i l afieaz ntr-o maniera convenabil. Putei ncerca asta asupra funciei de mai sus includei pur i simplu declaraiahelp(printMax) n program. Nu uitai s tastai q pentru a iei din help. Utilitarele pot colecta automat documentaia din programe n aceast maniera. De aceeav recomand insistent s folosii docstring pentru orice funcie nebanal pe care o scriei. Comanda pydoc inclus n distribuia Python funcioneaz similar cu help() folosind docstringurile. Adnotri Funciile mai au o facilitate avansat numit adnotare (engl. annotations) care este o cale deteapt de a ataa informaie pentru fiecare din parametri precum i pentru valoarea ntoars. ntruct limbajul Python n sine nu interpreteaz aceste adnotri n nici un fel (aceast funcionalitate este lsat bibliotecilor third-party s interpreteze ele n ce fel vor), vom trece peste aceast facilitate n discuia noastr. Dac suntei interesai despre adnotri, putei citi PEP No. 3107. Rezumat Am discutat multe aspecte ale funciilor, dar reinei c nu am acoperit toate aspectele posibile. Totui, am acoperit deja majoritatea aspectelor pe care le vom folosi n mod uzual. Vom afla n continuare cum s folosim, dar i s cream module Python.

Python ro:Module

Contents

1 Introducere 2 Fisiere .pyc compilate in octeti 3 Declaraia from import 4 Atributul __name__ al modulului 5 Crearea propriilor module 6 Funcia dir 7 Pachete 8 Rezumat

Introducere Ai vzut cum se poate refolosi o poriune de cod n program prin definirea funciilor. Dar dac vrei s refolosii un numr mai mare de funcii n alte programe dect cel pe care l scriei? Aa cum ai ghicit, rspunsul este folosirea modulelor. Exist variate metode de a scrie module, dar cea mai simpl cale este de a crea un fiier cu extensia .py care conine funcii i variabile. Alt metod este scrierea modulelor n limbajul n care chiar interpretorul Python a fost scris. De exemplu, putei scrie module n limbajul de programare C i dupa compilare, ele pot fi folosite din codul Python cnd se folosete interpretorul Python standard. Un modul poate fi importat de un alt program pentru a folosi funcionalitatea acestuia. Aa putem i noi s folosim biblioteca standard Python. nti vom vedea cum se folosesc modulele bibliotecii standard. Exemplu:
#!/usr/bin/python # Fiier: using_sys.py import sys print('Argumentele la linia de comand sunt:') for i in sys.argv: print(i) print('\n\nPYTHONPATH este', sys.path, '\n')

Rezultat:
$ python using_sys.py noi suntem argumente Argumentele la linia de comand sunt: using_sys.py noi

suntem argumente

PYTHONPATH este ['', 'C:\\tmp', 'C:\\Python30\\python30.zip', 'C:\\Python30\\DLLs', 'C:\\Python30\\lib', 'C:\\Python30\\lib\\platwin', 'C:\\Python30', 'C:\\Python30\\lib\\site-packages']

Cum funcioneaz: La nceput importm modulul sys folosind declaraia import. n esen, asta i spune lui Python c vrem s folosim acest modul. Modulul sys conine funcionalitate legat de interpretorul Python i mediul su, system. Cnd Python execut declaraia import sys, el caut modulul sys. n acest caz, este vorba de un modul preinstalat i de aceea Python tie unde s-l gseasc. Dac nu ar fi fost un modul compilat, ci un modul scris n Python, interpretorul ar fi cutat n directoarele listate n variabila sys.path. Dac modulul este gsit, declaraiile din interiorul modului sunt executate. Observai c aceast iniializare este fcut numaiprima dat cnd importm un modul. Variabila argv din modulul sys este accesat folosind notaia cu puncte, adic sys.argv. Ea arat clar c acest nume este parte a modulului sys. Alt avantaj al acestei abordri este c numele nu d conflict cu nici o variabil argv folosit n program. Variabila sys.argv este o list de iruri (listele sunt explicate n detaliu n capitolul despre liste. n special, variabila sys.argv conine lista argumentelor din linia de comand adic acele argumente transmise programului prin adugarea lor la linia de comand care lanseaz programul. Daca folosii un IDE pentru a scrie i rula aceste programe, cutai n meniuri o cale de a specifica argumente la linia de comand. Aici, cnd se execut python using_sys.py noi suntem argumente, rulm modululusing_sys.py cu comanda python i celelalte lucruri care l urmeaz sunt transmise programului. Python pstreaz linia de comand n variabila sys.argv ca s le putem folosi. Reinei, numele scriptului care ruleaz este ntotdeauna primul argument din listasys.argv. Deci n acest caz vom avea 'using_sys.py' n poziia sys.argv[0], 'noi' n poziiasys.argv[1], 'suntem' n poziia sys.argv[2] i 'argumente' n poziia sys.argv[3]. Observai c Python ncepe numerotarea cu 0 nu cu 1.

Variabila sys.path conine lista numelor de director de unde pot fi importate module. Observai c primul sir din sys.path este vid asta arat c directorul curent este parte a variabilei sys.path ceea ce este totuna cu variabila de mediu PYTHONPATH. Acest comportament este prevzut pentru a permite importul direct al modulelor aflate n directorul curent. n caz contrar modulele care trebuie importate trebuie poziionate ntr-unul din directoarele listate n sys.path. Fisiere .pyc compilate in octeti Importul unui modul este relativ costisitor, astfel c Python face nite smecherii ca s l accelereze. O cale este s creeze fiiere compilate n octei (engl. byte-compiled) cu extensia .pyc care sunt nite forme intermediare n care Python transform programul (v amintii din capitolul introductiv cum lucreaz Python?). Acest fiier .pyc este util cnd importai un modul a doua oar din alte programe ele vor fi mult mai rapide ntruct partea de procesare legat de importul modulului este deja realizat. De asemenea, aceste fiiere compilate n octei sunt independente de platform. Not Fiierele .pyc sunt create de obicei n acelai director ca i fiierul .pycorespondent. Dac Python nu are permisiunea de a scrie fiiere n acel director, fiierele .pyc nu vor fi create. Declaraia from import Dac vrei s importai direct variabila argv n programul vostru (pentru a evita scrierea numelui sys. de fiecare dat), putei folosi declaraia from sys import argv. Dac vrei s importai toate numele folosite n modulul sys atunci putei folosi declaraia from sys import *. Funcioneaz pentru orice modul. n general, trebuie s evitai folosirea acestor declaraii i n schimb s folosii declaraiaimport. Ca s fie evitate orice conflicte de nume i programele s fie mai lizibile. Atributul __name__ al modulului Orice modul are un nume, iar declaraiile din modul pot gsi numele modulului. Este comod aa, mai ales n situaia particular n care se dorete aflarea regimului modulului (autonom sau importat). Cum am menionat anterior, cnd un modul este importat pentru prima dat, codul din modul este executat. Putem folosi acest concept pentru a altera comportamentul modulului dac programul este executat autonom i l putem lsa neschimbat dac modulul este importat din alt modul. Acestea sunt posibile folosind atributul __name__ al modulului. Exemplu:
#!/usr/bin/python # Fiier: using_name.py if __name__ == '__main__': print('Acest program ruleaz autonom') else: print('Acest program a fost importat din alt modul')

Rezultat:
$ python using_name.py Acest program ruleaz autonom

$ python >>> import using_name Acest program a fost importat din alt modul >>>

Cum funcioneaz: Orice modul Python are propriul atribut __name__ definit i dac acesta este '__main__', rezult c acel modul este rulat de sine stttor de ctre utilizator i putem lua msurile adecvate. Crearea propriilor module Crearea propriilor noastre module este uoar, ai fcut asta tot timpul! Asta din cauz c orice program Python este un modul. Trebuie doar s ne asigurm c fiierul are extensia.py. Urmtorul exemplu ar trebui s clarifice situaia. Exemplu:
#!/usr/bin/python # Fiier: meu.py def zisalut(): print('Salut, aici este modulul meu.') __versiune__ = '0.1' # Sfritul modulului meu.py

Mai sus a fost un model de modul. Aa cum vedei, nu este nimic deosebit n legtur cu modulele n comparaie cu programele Python obinuite. Vom vedea n continuare cum putem s folosim acest modul n programele noastre Python. Amintii-v c modulul ar trebui plasat n acelai director cu programul care l import sau ntr-un director listat n variabila sys.path.
#!/usr/bin/python # Fiier: meu_demo.py import meu

meu.zisalut() print ('Versiunea', meu.__versiune__)

Rezultat:
$ python meu_demo.py Salut, aici este modulul meu. Versiunea 0.1

Cum funcioneaz: Observai c folosim aceeai notaie cu punct pentru a accesa membrii modulului. Python refolosete cu spor aceeai notaie pentru a da un sentiment distinctiv Pythonic programelor, astfel nct s nu fim nevoii s nvm noi moduri de a face lucrurile. Iat o nou variant folosind sintaxa declaraiei from..import:
#!/usr/bin/python # Fiier: meu_demo2.py from meu import zisalut, __versiune__ zisalut() print('Versiunea', __versiune__)

Rezultatul programului meu_demo2.py este acelai ca i rezultatul programuluimeu_demo.py. Observai c dac ar fi existat un nume __versiune__ declarat n modulul care import modulul meu, ar fi aprut un conflict. i asta este probabil, ntruct este o practic uzual pentru fiecare modul s se declare versiunea sa folosind acest nume. De aceea este ntotdeauna recomandabil s se foloseasc declaraia import dei ar putea face programul un pic mai lung. S-ar mai putea folosi:
from meu import *

Astfel ar fi importate toate numele publice, precum zisalut dar nu s-ar importa__versiune__ pentru ca ncepe cu dublu underscore. Calea (Zen) n Python Un principiu director n Python este Explicit este mai bine dect implicit. Rulaiimport this pentru a afla mai multe i urmrii aceast discuie care enumer exemple pentru fiecare din principii. Funcia dir Putei folosi funcia predefinit dir pentru a lista identificatorii pe care i definete un obiect. De exemplu, pentru un modul, clasele i variabilele definite n acel modul.

Cnd furnizai un nume funciei dir(), ea ntoarce lista numelor definite n acel modul. Dac se lanseaz funcia fr argumente, ea ntoarce lista numelor definite n modulul curent. Exemplu:
$ python

>>> import sys # obine lista atributelor, n acest caz, pentru modulul sys >>> dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__', '__s tderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_compact_freelists', '_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', ' byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle' , 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'getcheckinterval', 'getdefaultencoding', 'getfil esystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'gettrace', 'getwindowsversion', 'hexversion', 'intern', 'maxsize', 'maxunicode ', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platfor m', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit ', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_in fo', 'warnoptions', 'winver'] >>> dir() # obine lista atributelor pentru modulul curent['__builtins__', '__doc__', '__name__', '__package__', 'sys'] >>> a = 5 # creaz o nou variabil, 'a' >>> dir() ['__builtins__', '__doc__', '__name__', '__package__', 'a', 'sys'] >>> del a # terge (engl. delete) un nume >>> dir() ['__builtins__', '__doc__', '__name__', '__package__', 'sys'] >>>

Cum funcioneaz: Pentru nceput, vedem folosirea funciei dir asupra modulului importat sys. Putem vedea lista uria de atribute pe care o conine. Apoi folosim dir fr parametri. Implicit, ea ntoarce lista atributelor modulului curent. Observai c lista modulelor importate este inclus n lista modulului listat. Pentru a vedea funcia dir n aciune, definim o nou variabil, a, i i atribuim o valoare, apoi testm cu dir dac a aprut nc o valoare n lista de atribute a aceluiai nume. Eliminm variabila/atributul modulului curent folosind declaraia del i din nou schimbarea este reflectat n rezultatul funciei dir.

O not asupra declaraiei del aceast declaraie este folosit pentru a terge un nume de variabila i dup ce a fost executat (del a), nu mai putei accesa variabila a este ca i cum nu a existat niciodat. Reinei c funcia dir() lucreaz pe orice obiect. De exemplu, rulai dir(print) pentru a descoperi atributele funciei print sau dir(str) pentru atributele clasei str. Pachete La acest nivel, ai nceput probabil s observai o ierarhie n organizare a programelor. Variabilele sunt de obicei n interiorul funciilor. Funciile i variabilele globale intr n module. Dar modulele cum se organizeaz? Aici intervin pachetele. Pachetele sunt nite foldere de module cu un fiier special __init__.py care indic lui Python c acel folder este special, deoarece conine module Python. S zicem c vrei s creai un pachet numit mapamond cu subpachetele asia, africa, etc. i aceste pachete conin la rndul lor module precum india, madagascar, romnia etc. Iat cum ai structura folderele:
- <un folder prezent n sys.path>/ - mapamond/ - __init__.py - asia/ - __init__.py - india/ - __init__.py - foo.py - africa/ - __init__.py - madagascar/ - __init__.py - bar.py

- europa/ - __init__.py - romnia/ - __init__.py - foo_bar.py

Pachetele sunt doar un mod convenabil de a organiza ierarhic modulele. Vei vedea de multe ori asta n biblioteca Python standard. Rezumat Aa cum funciile sunt pri reutilizabile de program, modulele sunt programe (ntregi) reutilizabile. O alt ierarhie de organizare a modulelor o reprezint pachetele. Biblioteca standard care vine cu Python este un exemplu de set de pachete i module. Am vzut cum se folosesc modulele i cum se creeaza module proprii. n continuare vom nva despre cteva concepte interesante numite structuri de date.

Python ro:Structuri de date


Contents

1 Introducere 2 Liste 2.1 Introducere rapid n obiecte i clase 3 Tupluri 4 Dicionare 5 Secvene 6 Seturi 7 Referine 8 Alte detalii despre iruri 9 Rezumat

Introducere Structurile de date sunt n esen exact asta structuri care pot memora date grupate. Cu alte cuvinte, sunt folosite pentru a stoca colecii de date nrudite. Exist patru structuri predefinite n Python liste, tupluri, dicionare i seturi. Vom nva s le folosim pe fiecare i cum ne pot uura ele viaa.

Liste O list (engl. list) este o structur de date care pstreaz o colecie ordonat de elemente deci se poate memora o secven de elemente ntro list. Asta este uor de imaginat dac ne gndim la o list de cumprturi, numai c pe list fiecare item ocup un rnd separat, iar n Python punem virgule intre ele. Elementele listei trebuie incluse n paranteze drepte astfel nct Python s neleag c este o specificare de list. Odat ce am creat lista, putem aduga, terge sau cuta elemente n ea. De aceea se poate spune c listele sunt muabile, acest tip de date poate fi modificat.

INTRODUCERE RAPID N OBIECTE I CLASE

Dei n general am amnat discutarea obiectelor i claselor pna acum, este necesar o scurt introducere, pentru a se putea nelege listele mai bine. Detaliile le vom afla n capitolul dedicat acestora. O list este un exemplu de utilizare a obiectelor i claselor. Cnd folosim o variabil i i i atribuim o valoare, s zicem ntregul 5, putem gndi c am creat un obiect (de fapt instan) i din clasa (de fapt tipul) int. De fapt se poate citi help(int) pentru o nelegere mai aprofundatat. O clas poate avea i metode adic funcii definite pentru a fi folosite exclusiv n raport cu acea clas. Putei folosi aceste funcionaliti numai asupra unui obiect din acea clas. De exemplu, Python ofer o metod append pentru clasa list care ne permite s adugm un element la sfritul listei. Prin urmare lista_mea.append('un item') va aduga acel ir lalista_mea. De reinut folosirea notaiei cu punct pentru accesarea metodelor obiectelor. O clas poate avea i cmpuri (engl. fields) care nu sunt altceva dect variabile definite n raport exclusiv cu acea clas. Se pot folosi acele variabile/nume numai n raport un obiect din acea clas. Cmpurile sunt accesate tot prin notaia cu punct, de exemplu lista.cmp. Exemplu:
#!/usr/bin/python # Fiier: using_list.py # Lista mea de cumprturi shoplist = ['mere', 'mango', 'morcovi', 'banane'] print('Am de cumprat', len(shoplist), 'itemuri.') print('Acestea sunt:', end=' ') for item in shoplist: print(item, end=' ') print('\nTrebuie s cumpr i orez.') shoplist.append('orez') print('Lista mea de cumprturi este acum', shoplist)

print('Acum vom sorta lista') shoplist.sort() print('Lista sortat este', shoplist) print('Primul lucru de cumprat este', shoplist[0]) item_cumprat = shoplist[0] del shoplist[0] print('Am cumprat', item_cumprat) print('Lista mea este acum', shoplist)

Rezultat:
$ python using_list.py Am de cumprat 4 itemuri. Acestea sunt: mere mango morcovi banane Trebuie s cumpr i orez. Lista mea de cumprturi este acum ['mere', 'mango', 'morcovi', 'banane', 'orez'] Acum vom sorta lista Lista sortat este ['banane', 'mango', 'mere', 'morcovi', 'orez'] Primul lucru de cumprat este banane Am cumprat banane Lista mea este acum ['mango', 'mere', 'morcovi', 'orez']

Cum funcioneaz: Variabila shoplist este o list de cumprturi pentru cineva care merge la pia. n shoplist, memorm iruri care reprezint numele lucrurilor pe care le avem de cumprat, dar putem aduga orice fel de obiect inclusiv numere sau alte liste. Am folosit bucla for..in pentru a itera prin itemurile listei. Pn acum cred c ai realizat ca o list este i secven n acelai timp. Specificul secvenelor va fi discutat ntrunsubcapitol urmtor.

Observai utilizarea argumentului cuvnt cheie end al funciei print pentru a-i transmite c vrem s ncheiem linia cu un spaiu ( ) n loc de ncheierea uzual. n continuare adugm un item la list folosind metoda append a obiectului list, aa cum am discutat anterior. Verificm c adugarea s-a realizat tiprind coninutul listei prin transmiterea ei funciei print care o tiprete frumos pe ecran. Mai departe sortm lista folosind metoda sort a listei. Este important s ntelegem c aceast metod afecteaza nsi lista i nu ntoarce o list modificat spre deosebire de comportamentul sirurilor. Asta vrem s zicem prin muabile pe cnd irurile sunt imuabile. Dup ce cumprm un item de la pia, vrem s-l eliminm din list. Pentru aceasta utilizm declaraia del. Trebuie menionat aici itemul pe care vrem s-l eliminm i declaraia del l elimin pentru noi. Specificm c vrem s eliminm primul item, de aici declaraia del shoplist[0] (amintii-v c Python ncepe numrtoarea de la 0). Dac vrei s tii toate metodele definite de obiectul list, citii help(list). Tupluri Tuplurile sunt folosite pentru pstra colecii de obiecte. Sunt similare cu listele, dar fr funcionalitatea extins pe care o dau clasele. O facilitate major a tuplurilor este c ele sunt imuabile ca i irurile adic nu pot fi modificate. Tuplurile sunt definite prin specificarea itemurilor separate prin virgule ntro pereche opional de paranteze. Tuplurile sunt folosite de obicei n cazurile n care o declaraie sau o funcie definit de utilizator poate presupune fr risc de greeal c o colecie de valori nu se va schimba.. Exemplu:
#!/usr/bin/python # Fiier: using_tuple.py zoo = ('piton', 'elefant', 'pinguin') # reinei c parantezele sunt opionale print('Numrul animalelor n zoo este', len(zoo)) zoo_nou = ('maimu', 'cmil', zoo) print('Numrul de cuti n noul zoo este', len(zoo_nou)) print('Animalele din noul zoo sunt ', zoo_nou) print('Animalele aduse din vechiul zoo sunt ', zoo_nou[2]) print('Ultimul animal adus din vechiul zoo este', zoo_nou[2][2]) print('Numrul de animale n noul zoo este', len(zoo_nou)-1+len(zoo_nou[2]))

Rezultat:
$ python using_tuple.py Numrul animalelor n zoo este 3

Numrul de cuti n noul zoo este 3 Animalele din noul zoo sunt ('maimu', 'cmil', ('piton', 'elefant', 'pinguin')) Animalele aduse din vechiul zoo sunt ('piton', 'elefant', 'pinguin') Ultimul animal adus din vechiul zoo este pinguin Numrul de animale n noul zoo este 5

Cum funcioneaz: Variabila zoo este un tuplu de itemuri. Vedem c funcia len lucreaz i pentru tupluri. De asemenea asta arat c tuplurile sunt i secvene. Acum mutm aceste animale ntr-un nou zoo, deoarece vechiul zoo s-a nchis, s zicem. Ca urmare tuplul zoo_nou conine nite animale care erau acolo mpreun cu animalele aduse din vechiul zoo. n realitate, acum, reinei c un tuplu n interiorul altui tuplu nu i pierde identitatea. Putem accesa itemurile din tuplu specificnd poziia ntro pereche de paranteze ptrate, ca pentru liste. Acesta se numete operator de indexare. Accesm al treilea item dinzoo_nou specificnd zoo_nou[2] i accesm al treilea item al tuplului zoo din tuplulzoo_nou specificnd zoo_nou[2][2]. E destul de simplu dup ce ai nteles regula. Paranteze Dei parantezele sunt opionale, eu prefer s le pun mereu, pentru a face evident c e vorba de un tuplu, n special pentru a evita ambiguitatea. De exempluprint(1,2,3) i print( (1,2,3) ) nseamn dou lucruri foarte diferite prima tiprete trei numere, iar a doua tiprete un tuplu (care conine trei numere). Tupluri cu 1 sau 0 elemente Un tuplu vid este construit folosind o pereche de paranteze goale myempty = (). Totui, un tuplu cu un singur element nu e aa de simplu. Trebuie s l specificai folosind virgula dup primul (i ultimul) element, ca Python s poat diferenia ntre tuplu i un alt obiect cuprins n paranteze ntro expresie deci va trebui s specificai singleton = (2 , ) dac vrei s se neleag tuplul care conine doar elementul 2. Not pentru programatorii n Perl

O list ntro list nu-i pierde identitatea adic nu este asimilat ca n Perl. Asta se aplic i pentru un tuplu ntrun tuplu, o list ntrun tuplu, un tuplu ntro list etc. n ce privete limbajul Python, ele sunt nite obiecte stocate n alte obiecte. Dicionare Un dicionar este ca o carte de adrese n care poi gsi adresa sau datele de contact ale persoanei doar tiindu-i numele, adic asociem chei (nume) cu valori (detalii). De observat c o cheie trebuie s fie unic, pentru a nu exista confuzii, exact ca atunci cnd nu poi deosebi dou persoane dac au acelai nume. Pe post de chei putei folosi numai obiecte imuabile (precum irurile), dar pe post de valori putem folosi orice fel de valori. n esen nseamn c ar trebui s folosim pe post de chei numai obiecte simple. Perechile cheie valoare sunt specificate ntrun dicionar folosind notaia d = {cheie1: valoare1, cheie2: valoare2 }. Observai c perechile cheie valoare sunt separate prin virgul, iar cheia este separat de valoare prin semnul dou puncte. Dicionarul este delimitat de o pereche de acolade. Reinei c ntrun dicionar perechile cheie valoare nu sunt ordonate n nici un fel. Dac vrei o anumit ordine, va trebui s l sortai singuri nainte de folosire. Dicionarele pe care le vei folosi sunt instane/obiecte ale clasei dict. Exemplu:
#!/usr/bin/python # Fiier: using_dict.py # 'ab' este o prescurtare de la 'a'ddress'b'ook ab = { 'Swaroop' : 'swaroop@swaroopch.com', 'Larry' : 'larry@wall.org', 'Matsumoto': 'matz@ruby-lang.org', 'Spammer' : 'spammer@hotmail.com'

} print("Adresa lui Swaroop este", ab['Swaroop']) # tergerea unei perechi cheie - valoare del ab['Spammer'] print('\nExist {0} contacte n address-book\n'.format(len(ab))) for nume, adresa in ab.items(): print('Contactai pe {0} la adresa {1}'.format(nume, adresa)) # Adugarea unei perechi cheie - valoare ab['Guido'] = 'guido@python.org'

if 'Guido' in ab: # OR ab.has_key('Guido') print("\nAdresa lui Guido este", ab['Guido'])

Rezultat:
$ python using_dict.py Adresa lui Swaroop este swaroop@swaroopch.com

Exist 3 contacte n address-book

Contactai pe Swaroop la adresa swaroop@swaroopch.com Contactai pe Matsumoto la adresa matz@ruby-lang.org Contactai pe Larry la adresa larry@wall.org

Adresa lui Guido este guido@python.org

Cum funcioneaz: Crem dicionarul ab folosind notaia deja discutat. Accesm perechile cheie valoare specificnd cheia i folosind operatorul de indexare, aa cum am discutat la liste i tupluri. Observai simplitatea sintaxei. Putem terge perechi cheie valoare folosind vechiul nostru prieten declaraia del. Pur i simplu specificm dicionarul i operatorul de indexare pentru cheia care trebuie tears i le dm declaraiei del. Nu este necesar s se cunoasc i valoarea asociata cheii pentru a realiza aceast operaie. n continuare accesm fiecare pereche cheie valoare din dicionar folosind metodaitems a dicionarului care ntoarce o list de tupluri n care fiecare tuplu conine o pereche de itemuri cheia urmat de valoare. Extragem aceast pereche i o atribuim variabilelornume i adres corespunztor pentru fiecare pereche folosind o bucl for..in n care tiprim aceste informaii. Putem aduga perechi noi cheie valoare prin simpla utilizare a operatorului de indexare pentru a accesa cheia i a atribui acea valoare, aa cum am fcut pentru Guido n cazul de mai sus.

Putem testa dac exist n dicionar o anumit pereche cheie valoare folosind operatorulin sau chiar metoda has_key a clasei dict. Putei consulta documentaia pentru o list complet a metodelor clasei dict folosind comanda help(dict). Argumente cuvnt cheie i dicionare ntr-o alt ordine de idei, dac ai folosit argumente cuvnt cheie n funcii, nseamn c ai folosit deja dicionare! Ia gndii-v: perechea cheie valoare este specificat n lista de parametri a definiiei funciei i cnd accesai variabilele, numele lor sunt chei de acces ale unui dicionar numit tabel de simboluri n terminologia proiectrii de compilatoare). Secvene Listele, tuplurile i irurile sunt exemple de secvene, dar ce sunt secvenele i ce le face att de speciale? Facilitatea cea mai important este c au teste de apartenen (adic expresiile in i not in) i operaii de indexare. Operaia de indexare ne permite s extragem direct un item din secven. Au fost menionate trei tipuri de secvene liste, tupluri i iruri i operaia de feliere, care ne permite s extragem o parte (engl. slice) din secven. Exemplu:
#!/usr/bin/python # Fiier: seq.py shoplist = ['mere', 'mango', 'morcovi', 'banane'] nume = 'swaroop' # Operaia de indexare sau 'subscriere' print('Itemul 0 este', shoplist[0]) print('Itemul 1 este', shoplist[1]) print('Itemul 2 este', shoplist[2]) print('Itemul 3 este', shoplist[3]) print('Itemul -1 este', shoplist[-1]) print('Itemul -2 este', shoplist[-2]) print('Caracterul 0 este', nume[0]) # Felierea unei liste print('Itemurile de la 1 la 3 sunt', shoplist[1:3]) print('Itemurile de la 2 la sfrsit sunt', shoplist[2:]) print('Itemurile de la 1 la -1 sunt', shoplist[1:-1]) print('Itemurile de la nceput la sfrit sunt', shoplist[:]) # Felierea unui ir print('Caracterele de la 1 la 3 sunt', nume[1:3]) print('Caracterele de la 2 la end sunt', nume[2:]) print('Caracterele de la 1 la -1 sunt', nume[1:-1])

print('Caracterele de la nceput la sfrit sunt ', nume[:])

Rezultat:
$ python seq.py Itemul 0 este mere Itemul 1 este mango Itemul 2 este morcovi Itemul 3 este banane Itemul -1 este banane Itemul -2 este morcovi Caracterul 0 este s Itemurile de la 1 la 3 sunt ['mango', 'morcovi'] Itemurile de la 2 la sfrit sunt ['morcovi', 'banane'] Itemurile de la 1 la -1 sunt ['mango', 'morcovi'] Itemurile de la nceput la sfrit sunt ['mere', 'mango', 'morcovi', 'banane'] Caracterele de la 1 la 3 sunt wa Caracterele de la 2 la sfrit sunt aroop Caracterele de la 1 la -1 sunt waroo Caracterele de la nceput la sfrit sunt swaroop

Cum funcioneaz: La nceput, vedem cum se folosesc indecii pentru a obine un element anume din secven. Asta se mai numete operaia de subscriere. De cte ori specificai un numr ntro pereche de paranteze drepte alturate unei secvene, Python v va extrage itemul corespunzator poziiei n secven. Reinei c Python ncepe numrtoarea de la 0. Astfelshoplist[0] extrage primul item i shoplist[3] l extrage pe al patrulea din secvena shoplist.

Indexul poate fi i un numr negativ, caz n care poziia este calculat de la sfritul secvenei. Din acest motiv shoplist[-1] indic ultimul item din secven, iar shoplist[-2]penultimul item. Operaia de feliere este folosit specificnd numele secvenei urmat de o pereche opional de numere separate prin semnul doua puncte (engl. colon) incluse n paranteze drepte. Observai c este foarte asemntor cu operaia de indexare folosit pn acum. De reinut c numerele sunt opionale, semnul dou puncte NU este opional. Primul numr (nainte de dou puncte) n operaia de feliere indic punctul unde ncepe felia, iar al doilea numr indic unde se temin. Dac nu este specificat primul numr, Python va ncepe cu nceputul secvenei. Dac este omis al doilea numr, Python se va opri la sfritul secvenei. Observai c felia ntoars (uneori se spune returnat) ncepecu poziia dat de primul numr, dar se ncheie imediat nainte de poziia dat de al doilea numr adic nceputul este inclus, sfritul nu este inclus n felie. Astfel, shoplist[1:3] ntoarce o felie din secvena care ncepe cu poziia 1, include poziia 2, dar nu include poziia 3 deci este ntoars o felie de dou itemuri. Similar, shoplist[:]ntoarce o copie a secvenei. Mai puteti face feliere i cu indeci negativi. Numerele negative sunt folosite pentru a indica poziii de la sfritul secvenei. De exemplu, shoplist[:-1] va ntoarce o felie din secven care exclude ultimul item din secven, dar include tot restul secvenei. De asemenea, putem da al treilea argument pentru feliere, care devine pasul de feliere (implicit pasul este 1):
>>> shoplist = ['mere', 'mango', 'morcovi', 'banane'] >>> shoplist[::1] ['mere', 'mango', 'morcovi', 'banane'] >>> shoplist[::2] ['mere', 'morcovi'] >>> shoplist[::3] ['mere', 'banane'] >>> shoplist[::-1] ['banane', 'morcovi', 'mango', 'mere']

Iat ce se ntmpl cnd pasul este 2, obinem itemurile cu poziiile 0, 2, Dac pasul este 3, obtinem itemurile din poziiile 0, 3, etc. ncercai variate combinaii de specificaii de feliere n modul interactiv, pentru a vedea imediat rezultatele. Marele avantaj al secvenelor este c putei accesa tuplurile, listele i irurile n acelai fel! Seturi

Seturile sunt colecii neordonate de obiecte simple. Acestea sunt folosite atunci cand existena unui obiect n colecie este mai important dect poziia lui sau numrul de apariii. Folosind seturi, putei testa apartenena, dac un set este subset al altui set, putei afla intersecia a dou seturi i aa mai departe.
>>> bri = set(['brazilia', 'rusia', 'india']) >>> 'india' in bri True >>> 'usa' in bri False >>> bric = bri.copy() >>> bric.add('china') >>> bric.issuperset(bri) True >>> bri.remove('rusia') >>> bri & bric # OR bri.intersection(bric) {'brazilia', 'india'}

Cum funcioneaz: Exemplul este autoexplicativ deoarece implic teoria de baz nvat la coala despre mulimi (seturi). Referine Cnd creai un obiect i i atribuii o valoare, variabila doar indic obiectul creat, nu reprezint obiectul nsui! Asta nseamn c numele variabilei este un indicator ctre acea parte a memoriei calculatorului n care este stocat obiectul. Acest fapt se numetelegare (engl. binding) a numelui la obiect. n general, nu trebuie s v ngrijorai de asta, dar exist un efect subtil datorat referinei de care trebuie s fii contieni: Exemplu:
#!/usr/bin/python # Fiier: reference.py print('Atribuire simpl') lista_iniial = ['mere', 'mango', 'morcovi', 'banane'] lista_mea = lista_iniial # lista_mea este doar un alt nume al aceluiai obiect! del lista_iniial[0] # Am cumprat primul item, deci s-l tergem din list print('lista initial este', lista_iniial) print('lista mea este', lista_mea) # Observai c ambele liste apar fr 'mere', confirmnd

# astfel c ele indic acelai obiect print('Copiere fcnd o felie intergal') lista_mea = lista_iniial[:] # Face o copie prin feliere integral del lista_mea[0] # eliminm primul item print('lista_iniial este', lista_iniial) print('lista_mea este', lista_mea) # Observai c acum cele dou liste sunt diferite?

Rezultat:
$ python reference.py Atribuire simpl lista_iniial este ['mango', 'morcovi', 'banane'] lista_mea este ['mango', 'morcovi', 'banane'] Copiere fcnd o felie intergal lista_iniial este ['mango', 'morcovi', 'banane'] lista_mea este ['morcovi', 'banane']

Cum funcioneaz: Partea principal a explicaiei se regsete n comentarii. Reinei c dac vrei s facei o copie a unei liste sau a unor obiecte complexe (nu simpleobiecte, cum ar fi ntregii), atunci trebuie s folosii felierea. Dac folosii atribuirea obinei nc un nume pentru acelai obiect i asta poate aduce probleme dac nu suntei ateni. Not pentru programatorii n Perl Reinei c o declaraie de atribuire pentru liste nu creeaza o copie. Va trebui s folosii felierea pentru a face o copie a secvenei. Alte detalii despre iruri Am discutat deja n detaliu despre iruri. Ce ar mai putea fi de tiut? Ei bine, tiai c irurile sunt obiecte i au metode care fac orice de la verificarea unor pri ale irului pn la eliminarea spaiilor?

Sirurile pe care le folosii n programe sunt obiecte din clasa str. Cteva metode utile sunt artate n exemplul urmtor. Pentru o list complet a metodelor, citii help(str). Exemplu:
#!/usr/bin/python # Fiier: str_methods.py nume = 'Swaroop' # Acesta este obiectul ir if name.startswith('Swa'): print('Da, irul ncepe cu "Swa"') if 'a' in nume: print('Da, irul conine subirul "a"') if name.find('war') != -1: print('Da, irul conine subirul "war"') delimitator = '_*_' Lista_mea= ['Brazilia', 'Rusia', 'India', 'China'] print(delimitator.join(lista_mea))

Rezultat:
$ python str_methods.py Da, irul ncepe cu "Swa" Da, irul conine subirul "a" Da, irul conine subirul "war" Brazilia_*_Rusia_*_India_*_China

Cum funcioneaz: Aici vedem o mulime de metode n aciune. Metoda startswith este folosit pentru a testa dac irul ncepe sau nu cu un ir dat. Operatorul in se folosete pentru a verifica includerea unui ir n irul dat. Metoda find este folosit pentru a gsi poziia unui ir dat n irul iniial, care ntoarce -1 dac nu a gsit nimic. Clasa str are i o metod simpatic join pentru a altura itemurile dintro secven, cu un ir pe post de delimitator ntre itemuri i intoarce un ir lung generat din toate acestea. Rezumat Am explorat diversele structuri de date predefinite n Python n detaliu. Aceste structuri de date vor deveni eseniale pentru scrierea de programe de dimensiuni rezonabile.

Acum c avem o mulime de elemente Python asimilate, vom vedea cum se proiecteaz i se scriu programe Python n lumea de zi cu zi.

Python ro:Rezolvarea problemelor


Am explorat diverse pri din limbajul Python i acum vom vedea cum conlucreaz acestea prin proiectarea i scrierea unui program care face ceva util. Ideea este de a nva cum s scriem un program Python propriu.

Contents

1 Problema 2 Soluia 3 A doua versiune 4 Versiunea a treia 5 Versiunea a patra 6 Alte rafinamente 7 Procesul de dezvoltare de software 8 Rezumat

Problema Problema este Vreau un program care s fac un backup al tuturor fiierelor mele importante. Dei aceasta este o problema simpl, nu avem destule informaii pentru a ncepe gsirea unei soluii. Se impune o analiz suplimentar. De exemplu, cum specificm care fiiere trebuie salvate? Cum vor fi ele stocate? Unde vor fi stocate? Dup o analiz corect a problemei, proiectm programul. Facem o list cu lucruri care descriu cum trebuie s funcioneze programul nostru. n acest caz, am creat lista urmtoare care descrie cum vreau EU s mearg. Dac facei voi proiectarea s-ar putea s rezulte o altfel de analiz, ntruct fiecare face lucrurile n felul lui, deci e perfect OK. 1. Fiierele i directoarele care trebuie salvate sunt specificate ntr-o list. 2. Backup-ul trebuie stocat n directorul principal de backup 3. Fiierele sunt stocate ntro arhiv zip. 4. Numele arhivei zip este data i ora. 5. Folosind comanda standard zip disponibil implicit n toate distribuiile Linux/Unix. Utilizatorii de Windows pot instala din pagina proiectului GnuWin32 i adaugaC:\Program Files\GnuWin32\bin la variabila de mediu PATH, similar modului n caream fcut pentru recunoaterea nsi a comenzii python. Reinei c putei folosi orice comand de arhivare

att timp ct aceast are o interfa linie de comand, ca s i putem transmite argumente din programul nostru. Soluia ntruct designul programului nostru este relativ stabil, putem scrie codul careimplementeaz soluia noastr.
#!/usr/bin/python # Fiier: backup_ver1.py import os import time # 1. Fiierele i directoarele de salvat sunt specificate ntr-o list. source = ['"C:\\My Documents"', 'C:\\Code'] # Observai c a fost nevoie de ghilimele duble n interiorul irului pentru a proteja spaiile din interiorul numelor. # 2. Salvarea (engl. backup) trebuie stocat n directorul principal de backup target_dir = 'E:\\Backup' # Nu uitai s schimbai asta cu directorul folosit de voi # 3. Fiierele sunt salvate ntro arhiv zip. # 4. Numele arhivei zip este data i ora curent target = target_dir + os.sep + time.strftime('%Y%m%d%H%M%S') + '.zip' # 5. Folosim comanda zip pentru a include fiierele i directoarele de salvat n arhiv zip_command = "zip -qr {0} {1}".format(target, ' '.join(source)) # Rulm comanda de backup if os.system(zip_command) == 0: print('Salvare reuit n ', target) else: print('Backup EUAT')

Rezultat:
$ python backup_ver1.py Salvare reuit n E:\Backup\20090208153040.zip

Acum suntem n faza de testare n care verificm dac programul nostru lucreaz corect. Dac nu se comport cum trebuie, va fi nevoie de debugging adic eliminarea erorilor din program. Dac programul nu va merge, punei o declaraie print(zip_command) imediat nainte de apelul os.system i rulai programul. Acum copiai comanda zip_command la promptul shell-ului i verificai dac merge pe cont propriu. Dac aceasta eueaz, citii manualul comenzii zip ca s aflai ce ar putea fi greit. Dac reuete, verificai programul Python ca s vedei dac este exact ca mai sus. Cum funcioneaz:

Vei observa cum am transformat designul n cod ntro manier pas cu pas. Utilizm modulele os i time importndu-le de la nceput. Apoi specificm directoarele care trebuie salvate n lista source. Directorul destinaie este locul unde stocm toate salvrile i acesta este specificat n variabila target_dir. Numele arhivei zip pe care o vom crea este data curent+ora curent pe care le gsim folosind funcia time.strftime(). Arhiva va avea extensia .zip i va fi stocat n directorul target_dir. Observai folosirea variabilei os.sep cea care ne d separatorul de director al sistemului vostru de operare; acesta va fi '/' n Linux i Unix, '\\' n Windows i ':' n Mac OS. Folosirea declaraiei os.sep n locul acestor caractere va face programul mai portabil ntre aceste sisteme. Funcia time.strftime() primete o specificaie ca aceea folosit n program. Specificaia%Y va fi nlocuit cu anul, fr secol. Specificaia %m va fi nlocuit cu luna, ca numar zecimal ntre 01 i 12 .a.m.d. Lista complet a specificaiilor poate fi gsit n Manualul de referin Python. Crem numele directorului destinaie folosind operatorul de adunare care concateneazirurile adic altur irurile i produce unul mai lung. Atunci noi crem un irzip_command care conine comanda pe care o vom executa. Putei verifica dac a rezultat o comand corect prin executarea ei de sine stttoare ntr-un shell (terminal Linux sau DOS prompt). Comanda zip pe care o folosim are cteva opiuni i parametri transmii. Opiunea -q este folosit pentru a indica modul de lucru tcut (engl. quiet). Opiunea -r specific modul recursiv de parcurgere a directoarelor, adic trebuie s includ i toate subdirectoarele i subdirectoarele acestora etc. Cele dou opiuni se combin i se specific pe scurt -qr. Opiunile sunt urmate de numele arhivei care va fi creat urmat de lista fiierelor i directoarelor de salvat. Convertim lista source ntr-un ir folosind metoda join a irurilor, pe care am nvat deja s-o folosim. n fine, rulm comanda folosind funcia os.system care execut comanda ca i cum ar fi fost lansat din sistem adic n shell ea ntoarce 0 dac comanda a fost executat cu succes, altfel ntoarce un cod de eroare. n funcie de rezultatul comenzii, tiprim pe ecran mesajul adecvat, cum c salvarea a reuit sau nu. Asta e, am creat un script care s faca un backup al fiierelor importante din sistem! Not pentru utilizatorii de Windows n locul secvenelor de evadare cu dublu backslash, putei folosi i iruri brute. De exemplu, folosii 'C:\\Documents' sau r'C:\Documents'. n orice caz, nu folosii'C:\Documents' ntruct vei ajunge s folosii o secven de evadare necunoscut,\D.

Acum c avem un script funcional de salvare, l putem rula de cte ori vrem s obinem o salvare a fiierelor. Utilizatorii de Linux/Unix sunt sftuii s foloseasc metode executabileaa cum am discutat n capitolele precedente, astfel ca ele s poat rula de oriunde, oricnd. Asta se numete faza de operare sau de distribuire a software-ului. Programul de mai sus funcioneaz corect, dar (de obicei) primul program nu funcioneaz cum ne-am atepta. De exemplu ar putea fi probleme dac nu am proiectat corect programul sau dac avem o eroare de dactilografiere n scrierea codului (engl. typo), etc. n modul adecvat, v vei ntoarce la faza de design sau debuggigg pentru a rezolva problema. A doua versiune Prima versiune a scriptului nostru funcioneaz. Totui, putem rafina programul pentru a lucra mai bine n utilizarea sa de zi cu zi. Asta se numete ntreinere sau mentenan a software-ului (engl. maintenance). Unul din rafinamentele pe care le-am considerat eu utile a fost un mecanism mai bun de denumire a salvrilor, folosind ora ca nume al fiierului, iar data ca nume de subdirector al directorului de backup care s conin salvrile din aceeai data. Primul avantaj este c salvrile vor fi stocate ntr-o manier ierarhic i vor fi mai uor de gestionat. Al doilea avantaj este c lungimea numelor de fiier va fi mai mult mai mic. Al treilea avantaj este c se va putea verifica mai uor dac au fost fcute salvri zilnic (n ziua n care nu s-a facut, directorul avnd ca nume acea dat lipsete, ntruct nu a fost creat).
#!/usr/bin/python # Fiier: backup_ver2.py import os import time # 1. Fiierele i directoarele de salvat sunt specificate ntro list. source = ['"C:\\My Documents"', 'C:\\Code'] # Observai c au fost necesare ghilimele duble pentru a proteja spaiile din interiorul numelor. # 2. Salvarea trebuie stocat n directorul principal de backup target_dir = 'E:\\Backup' # Nu uitai s schimbai asta cu directorul pe care l folosii voi # 3. Fiierele sunt salvate n fiiere zip. # 4. Data curent este numele subdirectorului din folderul principal azi = target_dir + os.sep + time.strftime('%Y%m%d') # Ora curent este numele arhivei zip acum = time.strftime('%H%M%S') # Crem subdirectorul, dac nu exista nainte if not os.path.exists(azi): os.mkdir(azi) # crem directorul print('Am creat cu succes directorul ', azi) # Numele fiierului arhiva zip

target = azi + os.sep + acum + '.zip' # 5. Folosim comanda zip pentru a colecta fiierele n arhiv. zip_command = "zip -qr {0} {1}".format(target, ' '.join(source)) # Rulm programul de salvare if os.system(zip_command) == 0: print('Salvare reuit n ', target) else: print('Salvare EUAT')

Rezultat:
$ python backup_ver2.py Am creat cu succes directorul E:\Backup\20090209 Salvare reuit n E:\Backup\20090209\111423.zip

$ python backup_ver2.py Salvare reuit n E:\Backup\20090209\111837.zip

Cum funcioneaz: Majoritatea codului ramne neschimbat. Schimbrile constau un testarea existenei directorului avnd ca nume data curent n interiorului directorului principal de backup folosind funcia os.path.exists. Dac acesta nu exist, l crem noi folosind funciaos.mkdir. Versiunea a treia A doua versiune merge bine cnd facem multe salvri, dar e greu de vzut ce este salvat n fiecare arhiva! De exemplu, poate am fcut o schimbare mare unui program sau unei prezentri i a vrea s asociez aceste schimbri cu numele programului sau prezentrii i arhiva zip. Aceasta se poate realiza uor prin ataarea unui comentariu furnizat de utilizator la numele arhivei zip. Not Urmtorul program nu funcioneaz, deci nu va alarmai, urmai-l totui, pentru c e o lecie n el.
#!/usr/bin/python # Fiier: backup_ver3.py import os import time

# 1. Fiierele i directoarele de salvat sunt specificate ntro list. source = ['"C:\\My Documents"', 'C:\\Code'] # Observai c a fost nevoie de ghilimele duble pentru a proteja spaiile din interiorul numelor. # 2. Salvarea trebuie stocat n directorul principal target_dir = 'E:\\Backup' # Nu uitai s schimbai asta cu ce folosii voi # 3. Fiierele sunt salvate ntro arhiv zip. # 4. Data curent este numele subdirectorului azi = target_dir + os.sep + time.strftime('%Y%m%d') # Ora curent este numele arhivei zip acum = time.strftime('%H%M%S') # Lum un comentariu de la utilizator pentru a crea numele comentariu = input('Introducei un comentariu --> ') if len(comentariu) == 0: # Verificai dac a fost introdus target = azi + os.sep + acum+ '_' + comentariu.replace(' ', '_') + '.zip' # Crem subdirectorul dac nu exist deja if not os.path.exists(azi): os.mkdir(azi) # Crem directorul print('Am creat cu succes directorul ', azi) # 5. Folosim comanda zip pentru a colecta fiierele n arhiva zip_command = "zip -qr {0} {1}".format(target, ' '.join(source)) # Rulm salvarea if os.system(zip_command) == 0: print('Salvare reuit n ', target) else: print('Salvare EUAT')

Rezultat:
$ python backup_ver3.py File "backup_ver3.py", line 25 target = azi + os.sep + now + '_' + ^ SyntaxError: invalid syntax

Cum (nu) funcioneaz: Acest program nu funcioneaz! Python spune c e undeva o eroare de sintax ceea ce nseamn c programul nu a fost bine scris, c nu respect structura pe care se ateapt Python s o gseasc acolo. Cnd vedem eroarea dat de Python, aflm i locul unde a detectat el eroarea. Deci ncepem eliminarea erorilor (engl. debugging) programului de la acea linie.

La o observaie atent, vedem ca o linie logic a fost extins pe dou linii fizice fr s se specifice acest lucru. n esen Python a gsit operatorul de adunare (+) fr vreun operand n acea linie i prin urmare nu tie cum s continue. V amintii c putem specifica trecerea unei linii logice pe urmtoarea linie fizic folosind un backslash la sfritul liniei fizice. Astfel facem corectura la progrmul nostru. Aceasta corecie a programului cnd gasim erori se numete depanare (engl. bug fixing). Versiunea a patra
#!/usr/bin/python # Fiier: backup_ver4.py import os import time # 1. Fiierele de salvat sunt specificate ntro list. source = ['"C:\\My Documents"', 'C:\\Code'] # Observai c a trebuit s punem ghilimele duble pentru a proteja spaiile din interiorul numelor. # 2. Salvarea trebuie stocat n directorul principal de backup target_dir = 'E:\\Backup' # Nu uiati s schimbai asta cu ceea ce folosii voi # 3. Salvrile se fac n arhive zip. # 4. Ziua curent este numele subdirectorului din directorul principal de backup azi = target_dir + os.sep + time.strftime('%Y%m%d') # Ora curent este numele arhivei zip acum = time.strftime('%H%M%S') # Acceptm un comentariu de la utilizator comentariu = input('Introducei un comentariu --> ') if len(comentariu) == 0: # Verificm dac a fost introdus un comentariu target = azi + os.sep + acum + '.zip' else: target = azi + os.sep + acum + '_' + \ comentariu.replace(' ', '_') + '.zip' # Crem subdirectorul, dac nu exista deja if not os.path.exists(azi): os.mkdir(azi) # crem directorul print('Am creat cu succes directorul ', today) # 5. Folosim comanda zip pentru a colecta fiierele n arhiv zip zip_command = "zip -qr {0} {1}".format(target, ' '.join(source)) # Rulm comanda de backup if os.system(zip_command) == 0: print('Salvare reuit n ', target) else: print('Salvare EUAT')

Rezultat:
$ python backup_ver4.py Introducei un comentariu --> noi exemple adugate

Salvare reuit n E:\Backup\20090209\162836_noi_exemple_adugate.zip

$ python backup_ver4.py Introducei un comentariu --> Salvare reuit n E:\Backup\20090209\162916.zip

Cum functioneaz: Acest program funcioneaz, acum! S parcurgem mbuntirile pe care i le-am adus n versiunea 3. Acceptm un comentariu de la utilizator folosind funcia input i apoi testm dac s-a introdus ceva sau nu calculnd lungimea irului introdus cu ajutorul funciei len. Dac utilizatorul a dat ENTER fr s introduc ceva (poate era doar un backup de rutin i n-au fost fcute modificri anume), apoi continum ca mai nainte. Totui, dac a fost introdus un comentariu, acesta este ataat numelui arhivei zip, chiar naintea extensiei .zip. Observai c nlocuim spaiile n comentariu cu underscore ca s fie mai uoar gestiunea fiierelor cu nume lungi. Alte rafinamente A patra versiune este una satisfctoare pentru majoritatea utilizatorilor, dar este mereu loc pentru mai bine. De exemplu se poate introduce un nivel de logoree (engl. verbosity) pentru program, cu ajutorul opiunii -v Pentru a face programul mai vorbre. Alt mbuntire posibil ar fi s permitem ca fiierele i directoarele de salvat s fie transmise scriptului la linia de comand. Noi le putem culege din lista sys.argv i le putem aduga la variabila list source folosind metoda extend a clasei list. Cea mai importanta extindere ar fi s nu folosim os.system ci direct modulele predefinitezipfile sau tarfile pentru a crea aceste arhive. Ele sunt parte a bibliotecii standard i sunt deja disponibile pentru a scrie un program fr dependente externe pentru programul de arhivare. Totui, am folosit os.system pentru crearea salvrilor din motive pedagogice, pentru ca exemplul s fie destul de simplu de nteles, dar i util. Putei ncerca s scriei a cincea variant folosind modulul zipfile n locul apeluluios.system? Procesul de dezvoltare de software Am trecut prin diverse faze n procesul de scriere a unui program. Aceste faze pot fi rezumate astfel: 1. Ce (Analiza) 2. Cum (Design) 3. Executare (Implementare)

4. Test (Testare i eliminare erori) 5. Utilizare (Operare sau distribuire) 6. Mentenan (Rafinare) O cale recomandat de a scrie programe este procedura urmat de noi la scrierea scriptului de salvare: facem analiza i designul. ncepem implementarea cu o versiune simpl. O testm i o depanm. O folosim pentru a ne asigura c merge cum ne-am propus. Acum i adugm noi faciliti pe care le dorim i parcurgem ciclul FACI TESTEZI UTILIZEZI de cte ori este nevoie. Reinei, Software-ul este crescut, nu construit. Rezumat Am vzut cum se creeaz un program/script Python i diferite stadii implicate de scrierea unui program. Ai putea considera util scrierea de programe proprii, att pentru acomodarea cu Python ct i pentru a rezolva probleme. n continuare vom discuta despre programarea orientat pe obiecte.

Python ro:Programare orientat pe obiecte


Contents

1 Introducere 2 self 3 Clase 4 Metodele obiectelor 5 Metoda __init__ 6 Variabile de clas, variabile de instan 7 Motenire 8 Rezumat

Introducere n toate programele folosite pn acum ne-am construit soluiile n jurul funciilor adic blocuri de declaraii care manipuleaz date. Acest mod de programare se numeteorientat pe proceduri. Exist i un alt mod de organizare a programelor, n care funcionalitatea i datele sunt mpachetate mpreun n uniti numite obiecte. Acest mod de structurare definete paradigma orientat pe obiecte. Aproape tot timpul putei folosi abordri procedurale n programare, dar cnd scriei programe mari sau avei de rezolvat probleme care sunt mai aproape de acest mod de structurare, putei folosi tehnicile de programare orientat pe obiecte..

Clasele i obiectele sunt dou aspecte ale programrii orientate pe obiecte. O clascreeaza un nou tip n care obiectele sunt instane ale clasei. O analogie este c putei avea variabile de tip int care se traduce prin aceea c variabilele care stocheaz ntregi sunt instane (obiecte) ale clasei int. Not pentru programatorii n limbaje cu tipuri statice Observai c pn i ntregii sunt tratai ca obiecte (ale clasei int). Asta e diferit de C++ i Java (n versiunile dinainte de 1.5) n care ntregii sunt tipuri primitive native. A se vedea help(int) pentru detalii despre clas. Programatorii n C# i Java 1.5 vor gsi o similaritate cu conceptele de ncapsulare i decapsulare. Obiectele pot stoca date folosind variabile obinuite care aparin obiectului. Variabilele care aparin unui obiect sunt numite cmpuri. Obiectele pot avea i funcionalitate folosind funcii care aparin clasei. Aceste funcii se munesc metode ale clasei. Aceast terminologie este important deoarece ne ajuta s difereniem ntre funcii i variabile independente i cele aparinnd unui obiect sau unei clase. mpreun, variabilele i funciile care aparin unei clase se numesc atribute ale clasei. Cmpurile sunt de dou tipuri ele pot aparine fiecrei instane/obiect al clasei sau pot aparine nsi clasei. Acestea sunt numite variabile de instan respectiv variabile ale clasei. O clas este creat folosind cuvntul cheie class. Cmpurile i metodele clasei sunt listate ntrun bloc indentat. self Clasele i metodele au o diferen specific fa de funciile obinuite ele trebuie s aib un prenume suplimentar care trebuie adugat la nceputul listei de parametri, dar nu trebuie s-i dai o valoare cnd apelai metoda, Python o va furniza. Aceast variabil special se refer la obiectul nsui (engl. self) i prin convenie este numit self. Cu toate acestea, dei putei s-i dai orice nume acestui parametru, este puternic recomandat s folosii numele self orice alt nume este dezaprobat. Exist multe avantaje n folosire numelui standard orice cititor al programului va nelege imediat despre ce este vorba i chiar mediile IDE (Integrated Development Environments) specializate te pot ajuta dac foloseti self. Not pentru programatorii n C++/Java/C# self din Python este echivalent cu pointerul this din C++ i cu referina this din Java i C#.

Probabil v ntrebai cum d Python valoarea corect lui self i de ce nu trebuie s-i dm o valoare. Un exemplu va clarifica aceast problem. S zicem c avei o clas numitMyClass i o instan a acestei clase, numit myobject. Cnd apelai o metod a acestui obiect myobject.method(arg1, arg2), apelul este automat convertit de Python nMyClass.method(myobject, arg1, arg2) asta e toat marea specialitate a lui self. Asta nseamn i c dac avei o metod care nu primete argumente, tot va trebui s avei un argument self. Clase Cea mai simpl clas posibil este artat n exemplul urmtor.
#!/usr/bin/python # Fiier: simplestclass.py class Persoana: pass # Un bloc gol p = Persoana() print(p)

Rezultat:
$ python simplestclass.py <__main__.Persoana object at 0x019F85F0>

Cum funcioneaz: Crem o clas nou folosind declaraia class i numele clasei. Aceasta este urmat de un bloc indentat de declaraii care formeaz corpul clasei. n acest caz avem un bloc gol, artat de declaraia pass. n continuare crem un obiect/instan a acestei clase folosind numele clasei urmat de o pereche de paranteze. (Vom nva mai multe despre instaniere n paragraful urmtor). Pentru propria verificare, confirmm tipul variabilei prin simpla ei tiprire. Aflm c avem o instan a variabilei din clasa Persoana din modulul __main__. Observai c a fost tiprit i adresa unde este stocat obiectul n memoria calculatorului. Adresa aceasta va avea o valoare diferit n alt calculator deoarece Python l stocheaz unde are loc. Metodele obiectelor Am discutat deja c obiectele/clasele pot avea metode, exact ca funciile, doar c au un argument self n plus. Iat un exemplu.
#!/usr/bin/python # Fiier: metoda.py class Persoana:

def ziSalut(self): print('Salut, ce mai faci?') p = Persoana() p.ziSalut() # Acest exemplu poate fi scris i ca Persoana().ziSalut()

Rezultat:
$ python metoda.py Salut, ce mai faci?

Cum funcioneaz: Aici vedem particula self n aciune. Observai c metoda ziSalut nu primete parametri, dar tot are argumentul self n definiia funciei. Metoda __init__ Exist multe nume de metode care au un nteles special n clasele Python. Acum vom afla semnificaia metodei __init__. Metoda __init__ este executat imediat ce este instaniat un obiect al clasei. Metoda este util pentru a face iniializarea dorit pentru obiectul respectiv. Observai c numele este ncadrat cu dublu underscore. Exemplu:
#!/usr/bin/python # Fiier: class_init.py class Persoana: def __init__(self, nume): self.nume = nume def ziSalut(self): print('Salut, numele meu este ', self.nume) p = Persoana('Swaroop') p.ziSalut() # Acest exemplu putea fi scris Persoana('Swaroop').ziSalut()

Rezultat:
$ python class_init.py Salut, numele meu este Swaroop

Cum funcioneaz:

Definim metoda __init__ s ia un parametru nume (pe lng obinuitul self). n acest caz crem doar un cmp numit nume. Observai c dei ambele sunt numite nume, cele dou sunt obiecte diferite. Notaia cu punct ne permite s le deosebim. Cel mai important, observai c nu apelm explicit metoda __init__ ci i transmitem argumentele n parantez dup numele clasei n momentul crerii obiectului/instana a clasei. Aceasta este semnificaia acestei metode. Acum putem s folosim cmpul self.name n metodele noastre, ceea ce este artat n metoda ziSalut. Variabile de clas, variabile de instan Am discutat deja partea de funcionalitate a claselor i obiectelor (adic metodele), acum s nvm ceva despre partea de date. Partea de date, aa-numitele cmpuri, nu sunt altceva dect variabile obinuite care sunt legate de spaiile de nume ale claselor i obiectelor. Asta nseamn c aceste nume sunt valabile numai n contextul claselor i obiectelor respective. Din acest motiv acestea sunt numite spaii de nume (engl. name spaces). Exist dou feluri de cmpuri variabile de clasa i variabile de obiect/instan, care sunt clasificate n funcie de proprietarul variabilei. Variabilele de clas sunt partajate ele pot fi accesate de toate instanele acelei clase. Exist doar un exemplar al variabilei de clas i cnd o instan i modific valoarea, aceast modificare este vzut imediat de celelalte instane. Variabilele de instan sunt proprietatea fiecrei instane a clasei. n acest caz, fiecare obiect are propriul exemplar al acelui cmp adic ele nu sunt relaionate n nici un fel cu cmpurile avnd acelai nume n alte insante. Un exemplu va ajuta la nelegerea situaiei:
#!/usr/bin/python # Fiier: objvar.py clasa Robot: '''Reprezint un robot cu nume.''' # O variabil de clas, numrtorul populaiei de roboi populaie = 0 def __init__(self, nume): '''Iniializeaz datele.''' self.nume = nume print('(Iniializez robotul {0})'.format(self.nume)) # Cnd aceast instan este creat, robotul se # adaug la populaie Robot.populaie += 1 def __del__(self):

'''Dispar...''' print('{0} este dezmembrat!'.format(self.nume)) Robot.populaie -= 1 if Robot.populaie == 0: print('{0} a fost ultimul.'.format(self.nume)) else: print('Mai exist {0:d} roboi api de lucru.'.format(Robot.populaie)) def ziSalut(self): '''Salutare de la robot. Da, pot s fac i asta.''' print('Salut. Stpnii mei mi zic {0}.'.format(self.nume)) def ci(): '''Tiprete populaia curent.''' print('Avem {0:d} roboi.'.format(Robot.populaie)) ci = staticmethod(ci) droid1 = Robot('R2-D2') droid1.ziSalut() Robot.ci() droid2 = Robot('C-3PO') droid2.ziSalut() Robot.ci() print("\nRoboii pot s fac nite treab aici.\n") print("Roboii au terminat treaba. Deci s-i distrugem.") del droid1 del droid2 Robot.ci()

Rezultat:
(Iniializez robotul R2-D2) Salut. Stpnii mei mi zic R2-D2. Avem 1 roboi. (Iniializez robotul C-3PO)

Salut. Stpnii mei mi zic C-3PO. Avem 2 roboi.

Roboii pot s fac nite treab aici.

Roboii au terminat treaba. Deci s-i distrugem. R2-D2 este dezmembrat! Mai exist 1 roboi api de lucru. C-3PO este dezmembrat! C-3PO a fost ultimul. Avem 0 roboi.

Cum funcioneaz: Este un exemplu lung, dar ajut la evidenierea naturii variabilelor de clas i de instan. Aici cmpul populaie aparine clasei Robot i este deci o variabil de clas. Variabilanume aparine obiectului (i este atribuit folosind self.) deci este o variabil de obiect/instan. Asadar ne referim la variabila de clas populaie cu notaia Robot.populaie i nu cuself.populaie. Ne referim la variabila de instan nume cu notaia self.nume n metodele acelui obiect. Amintiiv aceast diferen simpl ntre variabilele de clas i de instan. Mai observai i c o variabil de obiect cu acelai nume ca o variabil de clas, va ascunde variabila de clas fa de metodele clasei! Metoda ci este n fapt o metod a clasei i nu a instanei. Asta nseamn c trebuie s o definim cu declaraia classmethod sau staticmethod Dac vrem s tim crui spaiu de nume i aparine. ntruct nu vrem aceasta informaie, o vom defini cu staticmethod. Am fi putut obine acelai lucru folosind decoratori:
@staticmethod def ci(): '''Tiprete populaia curent.''' print('Avem {0:d} roboti.'.format(Robot.populaie))

Decoratorii pot fi concepui ca scurtturi pentru apelarea unor declaraii explicite, aa cum am vzut n acest exemplu. Observai c metoda __init__ este folosit pentru a iniializa cu un nume instana claseiRobot. n aceast metod, mrim populaie cu 1 intruct a fost creat nc un robot. Mai observai i c valoarea self.nume este specific fiecrui obiect, ceea ce indic natura de variabil de instan a variabilei. Reinei c trebuie s v referii la variabilele i metodele aceluiai obiect numai cu self. Acest mod de indicare se numete referin la atribut.

n acest program mai vedem i docstrings pentru clase i metode. Putem accesa docstringul clasei n runtime (rom. timpul execuiei) folosind notaia Robot.__doc__ i docstring-ul metodei ziSalut cu notaia Robot.ziSalut.__doc__ Exact ca i metoda __init__, mai exist o metod special, __del__, care este apelat atunci cnd un obiect trebuie distrus, adic nu va mai fi folosit, iar resursele lui sunt returnate sistemului. n aceast metod reducem i numrul Robot.populaie cu 1. Metoda __del__ este executat dac obiectul nu mai este n folosin i nu exist o garanie c metoda va mai fi rulat. Dac vrei s o vedei explicit n aciune, va trebui s folosii declaraia del cum am fcut noi aici. Not pentru programatorii n C++/Java/C# Toi membrii unei clase (inclusiv membrii date) sunt publici i toate metodele suntvirtual n Python. O excepie: Dac folosii membrii date cu nume care ncep cu dublu underscoreprecum __var_privat, Python exploateaz acest aspect i chiar va face variabila s fie privat. Aadar, convenia este c orice variabil care vrem s fie folosit numai n contextul clasei sau obiectului, ar trebui s fie numit cu primul caracter underscore, iar toate celelalte nume sunt publice i pot fi folosite de alte clase/instane. Reinei c aceasta este doar o convenie i nu este impus de Python (exceptnd prefixul dublu underscore). Motenire Un beneficiu major al programrii orientate pe obiecte este refolosirea codului i o cale de a obine asta este mecanismul de motenire. Motenirea poate fi descris cel mai bine ca i cum ar implementa o relaie ntre un tip i un subtip ntre clase. S zicem c scriei un program n care trebuie s inei evidena profesorilor i studenilor ntr-un colegiu. Ei au unele caracteristici comune, precum nume, adres, vrst. Ei au i caracteristici specifice, cum ar fi salariul, cursurile i perioadele de absen, pentru profesori, respectiv notele i taxele pentru studeni. Putei crea dou clase independente pentru fiecare tip i procesa aceste clase prin adugarea de caracteristici noi. Aa programul devine repede un his necontrolabil.

O cale mai bun ar fi s creai o clas comun numit MembruAlcolii i s facei clasele student i profesor s moteneasc de la aceast clas, devenind astfel subclase ale acesteia, i apoi s adugai caracteristici la aceste subtipuri. Aceast abordare are multe avantaje. Dac facem vreo schimbare la funcionalitatea clasei MembruAlcolii, ea este automat reflectat i n subtipuri. De exemplu, putei aduga un nou cmp card ID i pentru studeni i pentru profesori prin simpla adugare a acestuia la clasa MembruAlcolii. Totui, schimbrile din subtipuri nu afecteaz alte subtipuri. Alt avantaj este c putei face referire la un profesor sau student ca obiectMembruAlcolii object, ceea ce poate fi util n anumite situaii precum calculul numrului de membri ai colii. Acest comportament este numit polimorfism, n care un subtip poate fi folosit n orice situatie n care se ateapt folosirea unui tip printe adic obiectul poate fi tratat drept instan a tipului printe. Observai i c refolosim codul clasei printe i nu e nevoie s-l repetm n subclase cum am fi fost nevoii dac am fi creat clase independente. Clasa MembruAlcolii n aceast situaie este numit clasa baz sau superclasa. Claseleprofesor i student sunt numite clase derivate sau subclase. Vom vedea acest exemplu pe un program.
#!/usr/bin/python # Fiier: inherit.py class MembruAlcolii: '''Reprezint orice membru al colii.''' def __init__(self, nume, vrst): self.nume = nume self.varsta = vrst print('(Iniializez MembruAlcolii: {0})'.format(self.nume)) def descrie(self): '''Afieaz detaliile mele.''' print('Nume:"{0}" Vrst:"{1}"'.format(self.nume, self.vrst), end=" ") class profesor(MembruAlcolii): '''Reprezint un profesor.''' def __init__(self, nume, vrst, salariu): MembruAlcolii.__init__(self, nume, vrst) self.salariu = salariu print('(Iniializez Profesor: {0})'.format(self.nume)) def descrie(self): MembruAlcolii.descrie(self) print('Salariu: "{0:d}"'.format(self.salariu)) class student(MembruAlcolii): '''Reprezint un student.''' def __init__(self, nume, vrst, note): MembruAlcolii.__init__(self, nume, vrst) self.note = note print('(Iniializez student: {0})'.format(self.nume))

def descrie(self): MembruAlcolii.descrie(self) print('Note: "{0:d}"'.format(self.note)) p = profesor('D-na. Shrividya', 40, 30000) s = student('Swaroop', 25, 75) print() # Afieaz o linie goal membri = [p, s] for membru in membri: membru.descrie() # Funcioneaz i pentru profesor i pentru student

Rezultat:
$ python inherit.py (Iniializez MembruAlcolii: Mrs. Shrividya) (Iniializez profesor: D-na. Shrividya) (Iniializez MembruAlcolii: Swaroop) (Iniializez student: Swaroop)

Nume:"D-na. Shrividya" Vrst:"40" Salariu: "30000" Nume:"Swaroop" Vrst:"25" Note: "75"

Cum funcioneaz: Pentru a folosi motenirea, specificm clasele baz ntrun tuplu care urmeaz numele n definiia clasei. Apoi observm c metoda __init__ a clasei baz este apelat explicit folosind variabila self ca s putem iniializa partea din obiect care provine din clasa baz. Este foarte important de reinut Python nu apeleaza automat constructorul clasei baz, trebuie s facei asta explicit. Mai observm c apelurile ctre clasa baz se fac prefixind numele clasei apelului metodelor i punnd variabila self mpreun cu celelalte argumente. Se confirm c folosim instanele claselor profesor i student ca i cum ar fi instane ale clasei MembruAlcolii cnd folosim metoda descrie a clasei MembruAlcolii. n plus, observai c este apelat metoda descrie a subtipului nu metoda descrie a claseiMembruAlcolii. O cale de a ntelege asta este c Python ncepe ntotdeauna cutarea

metodelor n tipul curent, ceea ce face n acest caz. Dac nu ar fi gsit metoda, ar fi cutat n clasele printe, una cte una, n ordinea specificat n tuplul din definiia clasei. O not asupra terminologiei daca n tuplul de motenire este listat mai mult de o clas, acest caz este de motenire multipl. Rezumat Am explorat diverse aspecte ale claselor i obiectelor precum i diferite terminologii asociate cu acestea. Am vzut de asemenea beneficiile i punctele slabe ale programrii orientate pe obiecte. Python este puternic orientat pe obiecte i nelegerea acestor concepte v va ajuta enorm n cariera de programator. Mai departe vom nva s tratm cu intrrile i ieirile i cum s accesam fiiere n Python.