Sunteți pe pagina 1din 104

Python ro:Prefaţă

Python este probabil singurul limbaj de programare care este şi simplu şi puternic. Asta e bine şi 
pentru începători şi pentru experţi şi, cel mai important, este distractiv să programezi cu el. Această 
carte îşi propune să ajute la învăţarea acestui limbaj minunat şi să arate cum se fac lucrurile repede 
şi fără probleme ­ ca urmare 'antivenin'­ul perfect pentru problemele tale de programare. 

Pentru cine este această carte 
Aceasta carte serveşte ca ghid sau tutorial pentru limbajul de programare Python. Este orientată în 
principal spre începători, dar este folositor şi pentru programatori avansaţi. 
Obiectivul este ca dacă tot ceea ce ştii despre calculatoare este cum să salvezi fişiere text, atunci să 
poţi învăţa Python din aceasta carte. Şi dacă ai experienţă prealabilă de programare, de asemenea 
poţi învăţa din aceasta carte. 
Dacă ai experienţă anterioară, vei fi preocupat de diferenţele între Python şi limbajul tău de 
programare favorit ­ am evidenţiat multe asemenea diferenţe. Un mic avertisment, totuşi: Python va 
ajunge în curând limbajul tău de programare favorit! 

Lecţie de istorie 
Am început lucrul cu Python când aveam nevoie să scriu un installer pentru un program pe care l­
am scris, numit 'Diamond' ca să fac instalarea uşoară. A trebuit să aleg între legăturile Python şi Perl 
pentru biblioteca Qt. Am căutat un pic pe net şi am găsit un articol unde Eric S. Raymond, faimosul 
şi respectatul hacker, vorbea despre cum a ajuns Python să devină limbajul său favorit. Am mai 
descoperit că legăturile PyQt erau mai mature comparativ cu legăturile Perl­Qt. Astfel am decis că 
Python era limbajul care îmi trebuie. 
Astea fiind făcute, am trecut la căutarea unei cărţi bune de Python. N­am găsit nici una! Am găsit 
nişte cărţi O'Reilly, dar erau fie prea scumpe fie erau mai mult manual de referinţe decât ghid. 
Aşadar m­am hotărât să folosesc documentaţia inclusă în limbaj. Totuşi, era prea scurtă şi concisă. 
Dădea o idee destul de bună despre Python, dar incompletă. M­am descurcat, fiindcă aveam 
experienţă anterioară, dar era neadecvată pentru începători. 
La circa şase luni după primul meu contact cu Python, am instalat (pe atunci) ultima versiune de 
Linux ­ Red Hat 9.0 ­ şi mă jucam cu KWord. M­a entuziasmat şi dintr­o dată mi­a venit ideea de a 
scrie ceva despre Python. Am început să scriu şi am ajuns repede la 30 de pagini. Pe urmă am căutat 
creşterea utilităţii documentaţiei mele în forma unei cărţi. După o mulţime de rescrieri, aceasta a 
atins un stadiu la care putea fi folosită ca ghid util pentru învăţarea limbajului Python. Consider 
această carte mica mea contribuţie la comunitatea open source. 
Cartea mea a început ca nişte note personale despre Python şi eu o consider aşa în continuare, deşi 
am făcut mari eforturi pentru a o face mai plăcută celorlalţi :) 
În adevăratul spirit open source, am primit o mulţime de sugestii, critici constructive şi reacţii de la 
cititori entuziaşti care m­au ajutat mult să îmbunătăţesc această carte. 

1
Starea cărţii 
Modificările de după ultima revizie majoră din martie 2005 sunt actualizari ale lansării Python 3.0 
(data de lansare estimată în August/Septembrie 2008). Începând cu Python 3.0, limbajul însuşi nu 
este încă finalizat/lansat, deci această carte va suferi constant modificări. Totuşi, în spiritul filosofiei 
open source "Lansează în devans, lansează frecvent", cartea actualizată a fost lansată şi va fi 
actualizată constant. 
Cartea necesită ajutorul cititorilor ei care sa indice orice părţi ale cărţii care nu sunt bune, nu sunt 
inteligibile sau sunt greşite. Vă rog scrieţi autorului principal sau traducătorilor comentariile şi 
sugestiile voastre. 
Este o luptă permanentă să cântăreşti între nevoile începătorului şi tendinţa spre 'completitudinea' 
informării. Ar fi folositor dacă cititorii ar lăsa şi reacţia lor în mesaje privind adâncimea până la care 
ar trebui să pătrundem în subiect. 

Website oficial 
Website­ul oficial al acestei cărţi este acesta, unde se poate citi întreaga carte online, descărca 
ultima versiune a cărţii, cumpăra o copie tipărită şi mi se pot trimite reacţiile faţă de carte. 

Licenţă 
1. Această carte este licenţiată sub licenţaCreative Commons Attribution­Share Alike 3.0 
Unported. 
• Ce înseamnă acest lucru: 
• Poţi copia, distribui şi transmite această carte mai departe 
• Poţi remixa conţinutul ­­ să­l adaptezi cum vrei 
• Sub următoarele condiţii: 
• Atribuire. Trebuie să specifici cui i se atribuie materialul original dar nu în 
aşa fel încât să se înţeleagă că autorul original îţi oferă suport. 
• Share Alike. Dacă modifici sau foloseşti această lucrare pentru a crea ceva pe 
baza acesteia, trebuie să distribui noul conţinut sub o licenţă similară şi 
compatibilă sau sub licenţa originală. 
• Pentru orice folosire sau distributie, trebuie să faci clară licenţa sub care se află acest 
material 
• Oricare dintre condiţiile de mai sus pot fi anulate doar cu permisiunea deţinătorului 
de copyright. 
• Nimic prevăzut în aceasta licenţă nu atacă drepturile morale ale autorului 
2. Atribuirea trebuie arătată prin adaugărea unui link înapoi la autor şi indicarea clară că textul 
original se poate downloada de la acea locaţie 
3. Întreg codul sursă din această carte este licenţiat sub licenţa BSD cu 3 menţiuni dacă nu se 
specifică altă licenţă 
4. Contribuţiile de voluntariat la materialul original trebuie să fie sub aceaşi licenţă iar 
copyrightul trebuie să rămână al autorului original al acestui material. 

2
Reacţii 
Am depus mult efort pentru a face cartea cât mai interesantă şi exactă. Totuşi, dacă apreciaţi unele 
părţi că sunt inconsistente sau incorecte sau pur şi simplu consideraţi că necesită îmbunătăţiri, vă 
rog să mă informaţi, ca să pot face modificările adecvate. Pot fi contactat prin intermediul paginii 
mele de utilizator. 

Cumpăraţi cartea 
Dacă vreţi să susţineţi dezvoltarea continuă a acestei cărţi, vă rog să luaţi în calcul posibilitatea de a 
cumpăra o copie tipărită sau de a face o donaţie. 

Subiect de gândire 
Există două căi de a face un design de software: una este de a­l face atât de simplu încât 
în mod evident nu are deficienţe; celălalt este de a­l face atât de complicat încât să nu­i 
fie evidente deficienţele. 
­­ C. A. R. Hoare 

Succesul în viaţă nu este atât o chestiune de talent şi oportunitate cât de concentrare şi 
perseverenţă. 
­­ C. W. Wendte 

3
Python ro:Introducere

Introducere 
Python este unul dintre puţinele limbaje de programare care pot susţine că sunt în acelaşi timp şi 
simple şi puternice. Vei realiza că vei fi în mod plăcut surprins de cât de uşor este să te concentrezi 
pe soluţia problemei şi nu pe sintaxa şi structura limbajului în care programezi. 
Textul de introducere oficial pentru Python este: 
Python este un limbaj uşor de învăţat şi puternic. Deţine structuri de date de nivel înalt 
eficiente şi o abordare simplă dar efectivă asupra programării orientate pe obiecte. 
Sintaxa elegantă a lui Python şi modul dinamic de selecţie a tipului de date, împreună cu 
natura sa de limbaj interpretat, îl face un limbaj ideal pentru scriptare şi pentru 
dezvoltare rapidă de aplicaţii în multe domenii şi pe majoritatea platformelor existente. 

Majoritatea facilităţilor sale vor fi discutate mai în detaliu în capitolul următor. 
Notă 
Guido van Rossum, creatorul limbajului Python, şi­a botezat limbajul dupa spectacolul BBC 
"Monty Python's Flying Circus" (Circul zburător al lui Monty Python). De fapt el nu prea 
agreează şerpii constrictori, care ucid animale pentru hrană strivindu­le. 

Facilităţile lui Python 
Simplu 
Python este un limbaj simplu şi minimalistic. Citirea unui program bine scris în Python dă 
aceeaşi senzaţie ca şi citirea unei nuvele în engleză, deşi cu o gramatică foarte strictă! Această 
natură de pseudocod a lui Python este una din marile sale puteri. Ea îţi permite să te 
concentrezi asupra soluţiei problemei mai degraba decât asupra limbajului însuşi. 

Uşor de învăţat 
Aşa cum vei vedea, cu Python este extrem de uşor de început. Python are o sintaxă 
extraordinar de simplă. 

Gratis şi open source 
Python este un exemplu de FLOSS (Free/Libre and Open Source Software). În termeni simpli, 
poţi distribui liber copii ale acestui software, citi codul sursă, modifica, folosi părţi din el în 
alte programe free. FLOSS se bazează pe conceptul de comunitate care pune cunoştinţe în 
comun. Acesta este unul din motivele pentru care Python este aşa de bun ­ el a fost creat şi 
îmbunătăţit constant de o comunitate care pur şi simplu îşi doreşte să vadă un Python tot mai 
bun. 

Limbaj de nivel înalt 
Când scrii programe în Python, nu ai nevoie să te preocupi de detalii de nivel scăzut precum 

4
managementul memoriei folosite de program etc... 

Portabil 
Prin natura sa open source, Python a fost portat (modificat ca să funcţioneze) pe multe 
platforme. Toate programele tale Python pot funcţiona pe oricare din aceste platforme, fără a 
necesita vreo modificare, dacă programezi cu grija de a evita facilităţile dependente de sistem 
ale limbajului. 
Poţi folosi Python pe Linux, Windows, FreeBSD, Macintosh, Solaris, OS/2, Amiga, AROS, 
AS/400, BeOS, OS/390, z/OS, Palm OS, QNX, VMS, Psion, Acorn RISC OS, VxWorks, 
PlayStation, Sharp Zaurus, Windows CE şi chiar pe PocketPC ! 

Limbaj interpretat 
Aici sunt necesare câteva explicaţii. 
Un program scris întrun limbaj compilat, precum C sau C++ este convertit din limbajul sursă 
întrun format acceptat de calculator (codul binar, cu 1 şi 0) folosind un compilator cu diverse 
comutatoare şi opţiuni. Când rulezi programul link­editat, software­ul copiază programul de 
pe harddisc şi începe să îl execute. 
Python, pe de altă parte, nu necesită compilare în binar. Pur şi simplu se lansează programul 
direct din codul sursă. Intern, Python converteşte codul sursă întrun format intermediar numit 
bytecodes (rom. şir de octeţi), apoi pe acesta îl transformă în limbajul nativ al computerului 
(cod maşină) şi apoi îl rulează. În fapt toate acestea fac utilizarea limbajului Python mult mai 
uşoară fiindcă nu mai trebuie să porţi grija compilării programului, a verificării alegerii link­
editarii şi încărcării corecte a bibliotecilor etc, etc. Din acelaşi motiv programele scrise în 
Python sunt mult mai portabile, doar le copiezi pe alt calculator şi imediat merg! 

Limbaj orientat pe obiecte 
Python suportă şi programarea procedurală, pe lângă programarea orientată pe obiecte. În 
limbajele orientate pe proceduri programele sunt construite în jurul procedurilor şi funcţiilor 
acestea nefiind altceva decât porţiuni de program reutilizabile. În limbajele orientate pe 
obiecte programul este construit În jurul obiectelor, care combină datele şi funcţionalitatea. 
Python are o metodă foarte puternică, dar simplă de a face programare orientată pe obiecte 
(OOP), în special în comparaţie cu marile limbaje precum Java sau C++. 

Extensibil 
Dacă ai nevoie ca o porţiune din codul programului să ruleze foarte rapid sau vrei ca unele 
soluţii de algoritm să nu fie open, poţi coda partea aceea în C sau C++ şi poţi apela acea parte 
direct din programul Python. 

Implantabil 
Se poate implanta cod Python în programe C/C++ pentru a le oferi facilităţi de 'scripting' 
utilizatorilor programelor. 

Biblioteci extinse 
Biblioteca standard Python este cu adevărat uriaşă. Te poate ajuta să rezolvi diverse probleme 
referitoare la expresii regulare, generare de documentaţie, testare de părţi, gestiune de fire de 
execuţie, baze de date, browsere web, CGI, ftp, email, XML, XML­RPC, HTML, fişiere 
.WAV, criptografie, GUI (graphical user interfaces), Tk şi alte lucruri dependente de sistem. 
Reţineţi, toate acestea sunt prezente unde este instalat Python. Acest lucru este aşa­numita 

5
filozofie 'cu baterii incluse' a limbajului Python. 
Pe lângă biblioteca standard există diferite alte biblioteci de foarte bună calitate, precum 
wxPython, Twisted, Python Imaging Library şi multe altele. 

Python este întradevăr un limbaj puternic şi antrenant. Are combinaţia corectă de performanţă şi 
facilităţi care fac scrierea de programe în Python şi distractivă şi uşoară. 

De ce nu Perl? 
Dacă nu ştiaţi deja, Perl este un alt limbaj de programare open­source interpretat. 
Dacă aţi fi încercat vreodată să scrieţi un program mare în Perl, v­aţi fi răspuns singuri la întrebare! 
Cu alte cuvinte programele în Perl sunt uşoare când sunt mici şi excelează la mici găselniţe şi 
scripturi de 'făcut treaba'. Oricum, ele devin rapid prea complexe îndată ce încep să crească şi vă 
spun asta din propria experienţă de autor de programe în Perl la Yahoo! 
Comparativ cu Perl, programele Python sunt clar mai simple, mai curate, mai uşor de scris şi astfel 
mai uşor de înţeles şi întreţinut. Eu admir Perl­ul şi îl folosesc zilnic pentru diverse lucruri, dar când 
încep să scriu un program încep prin a­l gândi în termenii de Python pentru că mie îmi vine mai 
natural aşa. Perl a suferit aşa de multe perfecţionări şi schimbări încât el pare a fi o mare (dar foarte 
utilă)găselniţă. Regretabil, dar aşteptatul Perl 6 nu pare a face progrese din acest punct de vedere. 
Singurul avantaj foarte semnificativ pentru Perl este reţeaua sa de arhive de module CPAN (the 
Comprehensive Perl Archive Network). Aşa cum sugerează şi numele ei, CPAN este o colecţie 
uriaşă de module Perl care impresionează prin extindere şi profunzime ­ folosind aceste module poţi 
face virtual orice. Unul din motivele pentru care Perl are mai multe module ca Python este acela că 
el a apărut mai demult decât Python. În orice caz, situaţia asta pare a se schimba datorită indexului 
Python Package Index de pachete Python. 

De ce nu Ruby? 
Dacă nu stiaţi deja, Ruby este un alt limbaj de programare open­source interpretat. 
Dacă deja apreciaţi şi folositi Ruby, atunci în mod cert vă recomand să continuaţi să­l folosiţi. 
Pentru ceilalti, care nu l­au folosit şi încearcă să judece dacă să înveţe Ruby sau Python, as 
recomanda Python, pe baza criteriului uşurinţei de învătare. Personal, l­am găsit greu de asimilat, 
dar cei ce înteleg Ruby propovăduiesc frumuseţea sa. Din nefericire nu sunt atât de norocos. 

Ce spun programatorii 
Poate vă interesează să citiţi părerea unor mari hackeri, precum ESR despre Python: 
• Eric S. Raymond este autorul lucrării 'Catedrala şi bazarul' fiind de asemenea părintele 
termenului 'Open Source'. El spune că Python a devenit limbajul său de programare favorit. 
Acel articol a fost o adevărată inspiraţie pentru abordarea primelor mele programe în 
Python. 
• Bruce Eckel este autorul faimoaselor cărţi 'Gândire în Java' şi 'Gândire în C++'. El spune că 
nici un limbaj de programare nu i­a adus o productivitate mai mare ca Python. În plus 
Python este probabil singurul limbaj focalizat pe a uşura munca programatorului. Citeşte 

6
interviul complet pentru alte detalii. 
• Peter Norvig este un binecunoscut autor de programe LISP, director de calitatea căutării la 
Google (mulţumiri lui Guido van Rossum pentru acest pont). El spune ca Python a fost 
întotdeauna parte integrantă din Google. Îi poţi verifica declaraţia pe pagina Google Jobs 
care arată cerinţa obligatorie de cunoştinţe de Python pentru inginerii de software. 

Despre Python 3.0 
Python 3.0 este noua versiune în devenire a limbajului. I se mai spune 'Python 3000' sau 'Py3K'. 
Motivul principal pentru o nouă versiune majoră a limbajului Python este eliminarea tuturor micilor 
probleme şi critici acumulate peste ani şi a face limbajul chiar mai curat. 
Daca ai deja mult cod Python versiunea 2.x, există un utilitar pentru a te ajuta să converteşti codul 
sursă din versiunea 2.x în versiunea 3.x. 
Mai multe detalii în: 
•  Introducerea lui Guido van Rossum  
•  Ce e nou în Python 2.6  (facilităţi sensibil diferite de versiunile 2.x precedente care probabil 
vor fi incluse în Python 3.0) 
•  Ce e nou în Python 3.0  
•  Python 2.6 şi graficul de lansare al versiunii 3.0  
•  Python 3000 (lista oficială definitivă a schimbărilor propuse)  
•  Diverse planuri Python 3.0  
•  Noutăţi Python (lista detaliată a modificărilor)  

7
Python ro:Instalare
Dacă aveţi deja instalat Python 2.x, nu aveţi nevoie să­l eliminaţi înainte de instalarea versiunii 
Python 3.0. Le puteţi avea pe ambele în acelaşi timp. 

Pentru utilizatorii Linux şi BSD 
Dacă folosiţi o distribuţie de Linux precum Ubuntu, Fedora, OpenSUSE sau {puneţi aici opţiunea 
voastră} sau un sistem BSD precum FreeBSD, atunci foarte probabil aveţi deja instalat Python în 
sistem. 
Pentru a verifica dacă aveţi Python deja instalat în sistemul Linux, deschideţi un program shell 
(precum konsole sau gnome-terminal) şi daţi comanda python -V cum este arătat mai 
jos. 
$ python -V
Python 3.0b1

Notă 
$ este promptul shellului. Acesta poate fi diferit pentru voi, în funcţie de setările sistemului de 
operare, de aceea eu îl voi arăta restrâns la doar simbolul $. 

Dacă se afişează informaţii despre versiune, înseamnă că aveţi deja instalat Python. 
Totuşi, dacă va da un răspuns ca mai jos: 
$ python -V
bash: Python: command not found

înseamnă că nu aveţi Python instalat. Asta este foarte atipic, dar posibil. 
În acest caz aveţi două căi de a instala Python în sistem. 
• Puteţi compila şi instala Python din codul sursă. Instrucţiunile de compilare sunt date în 
acelaşi website. 
• [Aceasta opţiune va fi disponibilă după lansarea finală a versiunii Python 3.0]. Instalaţi 
pachetele binare folosind programele de management de pachete specifice sistemului de 
operare (apt-get pentru Ubuntu/Debian şi altele bazate pe Debian, yum în Fedora, 
pkg_add în FreeBSD, etc.) Reţineţi că va trebui să aveţi acces internet pentru a folosi 
această opţiune. Alternativ, puteţi descărca executabilele binare precompilate pentru 
platforma voastră din altă parte şi le puteţi copia şi instala în PC. 

Pentru utilizatorii Windows 
Vizitaţi http://www.python.org/download/releases/3.0/ şi descarcaţi ultima versiune, care era 3.0 
beta 1 la momentul acestei scrieri. Sunt doar 12.8 MB ceea ce este foarte compact in comparaţie cu 
majoritatea altor limbaje şi softuri. Instalarea este la fel ca la orice software pentru Windows. 
Atenţionare 

8
Daca vi de da opţiunea de a debifa componente optionale, NU DEBIFAŢI NIMIC! Unele vă 
pot fi foarte folositoare, în special IDLE. 

Un fapt interesant este că majoritatea descărcărilor de Python sunt făcute de utilizatori Windows. 
Desigur, asta nu dă o imagine completă întrucât majoritatea utilizatorilor de Linux au Python 
preinstalat. 

DOS Prompt 
Daca vreţi să puteţi folosi Python de la linia de comandă Windows (sau DOS prompt), trebuie să 
setaţi corespunzator variabila %PATH%. 
În Windows 2000, XP, 2003, click pe Control Panel ­> System ­> Advanced ­> 
Environment Variables. Click pe variabila numită PATH în secţiunea 'System Variables', 
apoi selectaţi Edit şi adăugaţi ;C:\Python30 la sfârşitul a ceea ce există deja acolo. Desigur, 
folosiţi numele corect al directorului. 
Pentru versiuni mai vechi de Windows, adăugaţi în fişierul C:\AUTOEXEC.BAT urmatoarea linie: 
'PATH=%PATH%;C:\Python30' (fără ghilimele) şi restartaţi sistemul. În Windows NT, folosiţi 
fişierul AUTOEXEC.NT. 

Pentru utilizatorii de Mac OS X 
Utilizatorii de Mac OS X vor găsi Python preinstalat în sistem. Deschideţi Terminal.app, rulaţi 
python -V şi urmaţi recomandarea pentru utilizatorii de Linux. 

Rezumat 
Pe un sistem Linux, foarte probabil că deja aveţi Python instalat în sistem. În caz contrar, îl puteţi 
instala folosind programul de management de pachete specific distribuţiei de Linux respective. În 
cazul unui sistem Windows, instalarea lui Python este la fel de uşoară ca şi descărcarea installerului 
şi lansarea lui. De acum încolo vom presupune că aveţi Python instalat pe sistem. 
În continuare vom scrie primul nostru program în Python. 

9
Python ro:Primii paşi

Introducere 
Vom afla acum ce trebuie făcut pentru a rula tradiţionalul program 'Hello World' în Python. Astfel 
vom învăţa cum să scriem, salvăm şi rulăm programe Python. 
Sunt doua căi de a folosi Python pentru a rula un program ­ folosind promptul interactiv al 
interpretorului sau folosind fişierul sursă. Vom afla cum se folosesc ambele metode. 

Folosind promptul interpretorului 
Porniţi interpretorul de la linia de comandă introducând python la prompt. 
Pentru utilizatorii de Windows, puteţi rula interpretorul din linia de comandă dacă aveţi setată corect 
variabila PATH. 
Dacă folosiţi IDLE (de la Integrated Developpement Linux Environment), dati clic pe Start → 
Programs → Python 3.0 → IDLE (Python GUI). 
Acum introduceţi print('Hello World') urmat de tasta Enter. Ar trebui să vedeţi 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
>>>

Observaţi că Python va da rezultatul comenzii imediat! Ceea ce tocmai aţi introdus este o declaraţie 
Python singulară. Folosim print pentru (nesurprinzator) a tipări orice valoare pe care i­o 
furnizăm. Aici îi furnizăm textul Hello World şi acesta este tipărit rapid pe ecran. 
Cum să părăsiţi interpretorul 
Ca să părăsiţi prompt­ul, tastaţi Ctrl-D dacă folosiţi IDLE sau un shell Linux/BSD. În cazul 
consolei Windows (Command prompt), tastaţi Ctrl-Z urmat de tasta ENTER. 

Alegerea unui editor 
Înainte de a trece la scrierea de programe Python În fişiere sursă avem nevoie de un editor pentru a 
crea aceste fişiere. Alegerea editorului este crucială. Trebuie ales la fel ca şi maşinile. Un editor bun 
vă va ajuta să scrieţi programe Python uşor, făcând timpul petrecut o călătorie confortabilă şi vă va 
ajuta să ajungeţi la destinaţie (să vă atingeţi obiectivul) întro maniera rapidă şi sigură. 
O cerinţă de bază este evidenţierea sintaxei [1] în care diferitele componente ale sintaxei sunt 
colorate de aşa natură încât să poţi vizualiza programul şi rularea lui. 

10
Dacă utilizaţi Windows, vă recomand să folosiţi IDLE. IDLE face syntax highlighting şi multe 
altele printre care faptul că vă permite să rulaţi programele tot în IDLE. O notă specială: Nu folosiţi 
Notepad ­ este o opţiune rea fiindcă nu face syntax highlighting şi nu suportă indentarea textului, 
ceea ce este foarte important în cazul nostru, aşa cum veţi vedea în continuare. Editoarele bune 
precum IDLE (şi VIM) vă vor ajuta automat să indentaţi textul. 
Dacă utilizaţi Linux/FreeBSD, atunci aveţi o mulţime de opţiuni pentru editor. Dacă sunteţi chiar la 
începutul carierei de programator, poate o să preferaţi 'geany'. Are interfaţă grafică cu utilizatorul şi 
butoane speciale pentru compilat şi rulat programele Python fără complicaţii. 
Dacă sunteţi programator experimentat, atunci probabil că folosiţi deja Vim sau Emacs. Nu mai e 
nevoie să precizăm că acestea două sunt cele mai puternice editoare şi veţi avea nenumărate avantaje 
din folosirea lor la scrierea de programe Python. Eu personal folosesc Vim pentru majoritatea 
programelor. Dacă sunteţi programator începător, puteţi folosi Kate care este unul din favoritele 
mele. În cazul în care doriţi să alocaţi timpul necesar învăţării lucrului cu Vim sau Emacs, vă 
recomand să le învăţaţi pe amândouă, întrucât pe termen lung veţi culege foloase mult mai mari. 
În această carte vom folosi IDLE, editorul nostru IDE cel mai recomandat. IDLE este instalat în 
mod implicit de către installerele Python pentru Windows şi Mac OS X. Este disponibil şi pentru 
Linux şi BSD în colecţiile ('engl. repositories') respective. 
Vom explora folosirea mediului IDLE în capitolul următor. Pentru mai multe detalii, vă rog să 
vizitaţi documentaţia IDLE . 
Dacă tot mai doriţi să vedeţi şi alte opţiuni pentru editor, recomand cuprinzătoarea listă de editoare 
pentru Python şi să optaţi. Puteţi alege şi un IDE (Integrated Development Environment) pentru 
Python. A se vedea lista de medii integrate (IDE) care suportă Python pentru detalii suplimentare. 
Imediat ce veţi începe să scrieţi programe Python mari, IDE­urile pot fi cu adevărat foarte 
folositoare. 
Repet, vă rog să alegeţi un editor adecvat ­ el poate face scrierea de programe Python mai distractivă 
şi uşoară. 
Pentru utilizatorii de Vim 
Există o introducere bună despre 'Cum să faci Vim un IDE puternic pentru Python' de 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 fişier sursă 
Să ne întoarcem la programare. Există o tradiţie ca de câte ori înveţi un nou limbaj de programare, 
primul program pe care îl scrii să fie programul 'Hello World' ­ tot ce face el este să afişeze 'Hello 
World' când îl rulezi. După expimarea lui Simon Cozens [2], este 'incantaţia tradiţională către zeii 
programării ca sa te ajute să înveţi limbajul mai bine' :) . 
Porniţi editorul ales, introduceţi programul următor şi salvaţi­l sub numele helloworld.py 
Dacă folosiţi IDLE, daţi clic pe File → New Window şi introduceţi programul de mai jos. Apoi 
clic pe File → Save. 
#!/usr/bin/python

11
#Fisier: helloworld.py

print('Hello World')

Rulaţi programul deschizând un shell [3] şi introducând comanda python helloworld.py. 
Daca folosiţi IDLE, deschideţi meniul Run → Run Module sau direct F5 de pe tastatură. 
Rezultatul este afişat astfel: 
$ python helloworld.py
Hello World

Daca aţi obţinut rezultatul afişat mai sus, felicitări! ­ aţi rulat cu succes primul program în Python. 
În caz ca aţi obţinut un mesaj de eroare, vă rog, tastaţi programul anterior exact ca în imagine şi 
rulaţi programul din nou. De reţinut că Python este case­sensitive [4] aşadar print nu este acelaşi 
lucru cu Print ­ observaţi p minuscul în primul exemplu şi P majuscul în al doilea exemplu. De 
asemenea, asiguraţi­vă că nu există spaţii sau TAB înaintea primului caracter din fiecare linie ­ vom 
vedea mai târziu de ce este atât de important. 

Cum funcţionează 
Să considerăm 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 foloseşte comentarii numai pentru acest caz. Prima linie este numita linie shebang ­ de 
fiecare dată când începe cu #! urmată de locaţia unui program; asta spune sistemului nostru 
Linux/Unix că fişierul trebuie înteles prin acest interpretor atunci când este executat. O explicaţie 
mai detaliată va fi prezentată în capitolele următoare. De reţinut că puteţi rula oricând programul pe 
orice platformă specificând interpretorul în linia de comandă, ca în exemplul python
helloworld.py . 
Important 
Folosiţi cu grijă comentarii în programe pentru a explica detalii importante ale unor 
instrucţiuni ­ Asta va ajuta cititorul să înţeleagă mai uşor ce 'face' programul. Acel cititor 
puteţi fi dumneavoastră, peste şase luni! 

Comentariile sunt urmate de o declaraţie Python. În cazul nostru apelăm funcţia print care pur şi 
simplu tipăreşte pe ecran textul 'Hello World'. Vom învăţa despre funcţii într­un alt capitol; ce 
trebuie reţinut 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 ­ fiţi fără grijă, vom explora mai târziu 
terminologia aceasta în detaliu. 

Programe Python executabile 
Partea aceasta se aplică numai utilizatorilor de Linux/Unix, dar utilizatorii de Windows ar putea fi 
curioşi în legătură cu prima linie din program. Pentru început, va trebui să dăm fişierului 
permisiunea de a fi executabil folosind comanda chmod şi apoi să rulăm programul sursă. 
$ chmod a+x helloworld.py
$ ./helloworld.py
Hello World

12
Comanda chmod este folosită aici pentru a schimba [5] mod­ul fişierului dându­i drept de execuţie 
pentru toţi [6] utilizatorii sistemului. Pe urmă executăm programul direct, specificând locaţia 
programului sursă. Folosim ./ pentru a indica localizarea programului executabil în directorul 
curent. 
Pentru a face lucrurile şi mai distractive, puteţi redenumi fişierul cu numele helloworld şi îl 
puteţi rula cu ./helloworld şi tot va merge, folosind interpretorul de la locaţia specificată pe 
primul rând din fişier.. 
Ce e de făcut dacă nu ştim unde este localizat Python? Atunci puteţi folosi programul env specific 
sistemelor Linux. Modificaţi primul rând astfel: 
#!/usr/bin/env python

Programul env la rândul lui va căuta interpretorul Python care va rula programul. 
Până acum am putut să executăm programele noastre doar dacă ştiam calea exactă. Dar dacă dorim 
să rulăm programul din orice director? Putem să facem asta dacă memorăm programul întrunul din 
directoarele listate în variabila de mediu PATH. Oridecâte ori rulaţi 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 afişa conţinutul variabilei PATH folosind comanda echo şi prefixând numele variabilei cu 
caracterul $ pentru a­i transmite shell­ului că avem nevoie de valoarea acestei variabile. Observăm 
că /home/swaroop/bin este printre directoarele din PATH, unde swaroop este numele de 
utilizator [7] pe care eu îl folosesc în sistemul meu. Există unul similar pentru numele de utilizator 
al fiecaruia pe sistemul său. Ca alternativă, puteţi adăuga un director anume la variabila PATH ­ se 
face executând PATH=$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ă 
vreţi să scrieţi scripturi utile pe care vreţi să le rulaţi oricând din orice locaţie a sistemului. Seamănă 
cu a­ţi crea propriile comenzi, precum cd sau orice altă comandă pe care o execuţi în terminalul 
Linux sau DOS prompt. 
Atenţie 
Din punctul de vedere al Python­ului, program sau script sau software înseamnă acelaşi lucru! 

Cum obţinem ajutor 
Dacă aveţi nevoie repede de informaţii despre vreo funcţie sau declaraţie din Python, atunci puteţi 
apela la functionalitatea inclusă [8] help. Este foarte folositor, mai ales la promptul interpretorului. 
De exemplu rulaţi help(print) ­ se va afişa documentaţia de asistenţă pentru funcţia print
folosită pentru afişarea pe ecran. 
Notă 
Tastaţi q pentru a ieşi din help. 

13
Similar, puteţi obţine informaţii despre aproape orice din Python. Folosiţi help() pentru a afla 
mai multe despre însuşi help! 
În cazul în care aveţi nevoie de ajutor în legătură cu operatori precum return, atunci va trebui să­i 
puneţi în ghilimele (ca în help('return')) pentru ca Python să inţeleagă fără confuzie ce 
încercaţi să faceţi. 

Rezumat 
Acum ar trebui să puteţi scrie, salva şi rula cu uşurinţă programe Python. Pentru ca aţi devenit 
utilizator de Python, să mai învăţăm câteva concepte din Python. 

Referinţe: 
1.  ↑  engl. syntax highlighting 
2.  ↑  autorul minunatei cărţi 'Beginning Perl' 
3.  ↑  terminal Linux sau DOS prompt 
4.  ↑  sensibil faţă de cazul caracterelor n.tr. minuscule/majuscule 
5.  ↑  engl. change 
6.  ↑  engl. all 
7.  ↑  engl. username 
8.  ↑  engl. built­in

14
Python ro:Elemente
Simpla tipărire a textului 'Hello World' nu ajunge, aşa­i? Vreţi să faceţi mai mult de atât ­ vreţi să 
preluaţi ceva intrări, să le prelucraţi şi să obţineţi un rezultat. Putem face asta în Python folosind 
constante şi variabile. 

Constante literale 
O constanta literală este un număr precum 5, 1.23, 9.25e-3 sau un şir [1] precum 'Acesta
este un şir' sau "E string!". Se numeşte literal fiindcă este folosit literal ­ îi folosim 
valoarea literalmente. Numărul 2 se reprezintă întotdeauna pe sine şi nimic altceva ­ este o 
constantă 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 număr întreg. 
• Exemple de float sau floating point [2] sunt 3.23 şi 52.3E-4. Notaţia 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 experimentaţi 
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 experimentaţi 
Nu există şiruri "ASCII" pure pentru că Unicode este un superset al ASCII. Dacă se impune în 
program un flux de octeţi codat ASCII, atunci folosiţi str.encode("ascii"). Pentru 
detalii, urmăriţi discuţia pe acest subiect de la StackOverflow. 
Implicit, toate şirurile sunt în Unicode. 

Aproape pot garanta că veţi folosi şiruri în aproape toate programele Python pe care le scrieţi, aşa că 
acordaţi atenţie părţii următoare despre cum se folosesc şirurile în Python. 

Ghilimele simple 
Puteţi specifica şiruri folosind ghilimele simple [3] precum 'Citeaza-ma referitor la
acest subiect'. Tot spaţiul alb precum SPACE şi TAB sunt păstrate ca atare [4]. 

15
Ghilimele duble 
Şirurile în ghilimele duble [5] funcţioneaza la fel ca şi cele în ghilimele simple. De exemplu "Cum
te cheamă?" 

Ghilimele triple 
Puteţi specifica şiruri care se întind pe mai multe linii folosind ghilimele triple (engl. triple quotes) ­ 
(""" sau '''). Puteţi 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 numeşti?', l-a intrebat.
El a zis "Bond, James Bond".
'''

Secvenţe de evadare 
Să presupunem că vrem să utilizăm un şir care conţine un apostrof (una din ghilimele simple) '. 
Cum o să specificăm şirul What's your name?. Nu­l putem specifica 'What's your
name?' pentru că Python va confunda apostroful cu sfârşitul şirului. Într­un fel sau altul va trebui 
să specificăm că acel apostrof face parte din şir, nu este un delimitator. Pentru aceasta se foloseşte o 
secvenţă de evadare [6]. Specificăm apostroful \' ­ observaţi 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ă specificăm un şir pe două rânduri? O soluţie este să folosim ghilimele triple 
cum am văzut mai devreme, dar putem să folosim o secvenţă de evadare pentru sfârşitul 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 sfârşitul liniei arată continuarea şirului pe linia 
următoare, fără să se adauge caracterul newline. De exemplu: 
"Aceasta este prima propoziţie. \
Aceasta este a doua propoziţie".

este echivalent cu "Aceasta este prima propoziţie. Aceasta este a doua


propoziţie". 

Şiruri brute 
Dacă aveţi nevoie să specificaţi şiruri în care să nu fie procesate secvenţe de evadare trebuie să 
folosiţi şiruri brute [7] prefixând şirul cu r sau R. De exemplu r"Caracterul newline
este indicat de \n". 

16
Şirurile sunt imuabile 
Asta înseamnă că odată create, nu mai pot fi modificate. Deşi pare un lucru rău, nu este. Vom vedea 
în diferitele programe prezentate de ce asta nu este o limitare. 

Concatenarea literalilor şir 
Dacă se alătura doi literali, eu sunt concatenaţi 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 aşa ceva, 
deci sunt sigur că n­o să­i duceţi dorul. 

Notă pentru programatorii Perl/PHP 
Reţineţi ca şirurile delimitate de gihilimele simple sau duble sunt la fel, nu diferă prin nimic. 

Notă pentru utilizatorii de expresii regulare 
Folosiţi întotdeauna şiruri brute cand aveţi de­a face cu expresii regulare, altfel o să fie nevoie 
de multe căutări în urmă pentru a găsi ce nu merge. De exemplu referinţele retroactive [8] pot 
fi utilizate ca '\\1' sau r'\1'. 

Metoda format 
Uneori vrem să construim şiruri din alte informaţii. Aici este folositoare metoda format(). 
#!/usr/bin/python
# Fişier: str_format.py

vârstă = 25
nume = 'Swaroop'

print('{0} are {1} de ani.'.format(nume, vârstă))


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 funcţionează: 
Un şir poate folosi anumite specificaţii şi apoi poate apela metoda format pentru a substitui acele 
specificaţii care corespund argumentelor metodei format. 
Observaţi prima folosire, unde folosim {0} şi asta corespunde cu varibila nume care este primul 
argument al metodei format. Similar, a doua specificaţie este {1} corespunzatoare variabilei 
vârstă care este al doilea argument pentru metoda format. 
Observaţi că puteam obţine acelaşi lucru prin concatenare: nume + ' are ' +
str(vârstă) + ' de ani', dar uite ce urâtă şi predispusă la erori este această cale. În al 
doilea rând, conversia în şir este făcută automat de metoda format în locul unei conversii 
explicite. În al treilea rând, folosind metoda format putem schimba mesajul fără să avem de­a face 

17
cu variabilele şi reciproc. 
Ce face Python în metoda format este că înlocuieşte valoarea fiecărui argument în locurile 
specificate. Pot exista şi specificări mai detaliate, cum ar fi: 
>>> '{0:.3}'.format(1./3) # zecimal (.) precizie de 3 zecimale pentru float
'0.333'
>>> '{0:_^11}'.format('hello') # umple până 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 cuvinte-cheie
'Swaroop a scris Un pic de Python.'

Detalii despre aceste specificaţii de formatare sunt date în PEP 3101 (PEP=Python Enhancement 
Proposal). 

Variabile 
Folosirea exclusiv a literalilor poate deveni rapid plictisitoare ­ avem nevoie să stocăm orice 
informaţie şi să o prelucrăm. 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 nişte mici zone din memoria calculatorului unde se stochează nişte informaţie. Spre 
deosebire de constante, e nevoie de a accesa această informaţie, din acest motiv variabilele au nume. 

Nume de identificatori 
Variabilele sunt exemple de identificatori. Identificatorii sunt nume date pentru a identifica ceva. 
Există câteva 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ă aceeaşi variabilă. 
Observaţi minuscula n în primul caz şi majuscula N în al doilea. 
• Exemple de nume valide de identificator sunt i, __chiar_aşa, nume_23, a1b2_c3 şi 
resumé_count. 
• Exemple de nume invalide de identificator sunt 2chestii, asta contine spaţii ş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 învăţa cum să creăm propriile noastre 
tipuri de date, folosind clase. 

Obiecte 
Reţineţi, Python consideră că tot ce se foloseşte în program este obiect, în sens generic. În loc de a 

18
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 
funcţiile. 
Acum vom vedea cum se folosesc variabilele împreună cu literalii. Salvaţi următorul program şi 
rulaţi­l. 
Cum se scriu programele Python 
De acum încolo, procedura standard de a salva şi rula programele Python este astfel: 
1. Deschideţi editorul preferat. 
2. Introduceţi codul programului dat în exemplu. 
3. Salvaţi­l întrun fişier cu numele menţionat în comentariu. Eu urmez convenţia de a 
salva toate programele Python în fişiere cu extensia .py. 
4. Rulaţi­l folosind interpretorul cu comanda python program.py sau folosiţi IDLE 
pentru a rula programe. De asemenea puteţi folosi metoda executabilă cum am explicat 
mai devreme. 

Exemplu: Folosirea variabilelor şi a literalilor 
# Fişier : 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 funcţionează: 
Iată cum lucrează programul: întâi, atribuim valoarea constantei literale 5 variabilei i folosind 
operatorul de atribuire (=). Aceasta linie este o declaraţie deoarece susţine că trebuie făcut ceva, în 
acest caz, conectăm variabila i la valoarea 5. În continuare, tipărim valoarea lui i folosind 
declaraţia print care, previzibil, tipăreste valoarea variabilei pe ecran. 
Apoi adăugăm 1 la valoarea stocată în i şi păstrăm noul rezultat. Tipărim valoarea variabilei şi 
obţinem ce am prevăzut, valoarea 6. 
Similar, atribuim literalul şir variabilei s şi o tipărim. 
Notă pentru programatorii în limbaje cu tipuri statice 
Variabilele sunt folosite prin simpla atribuire a unei valori. Nu este necesară nici o declaraţie 

19
sau definiţie de tip de date. 

Linii logice şi linii fizice 
O linie fizică este ceea ce vedeţi când scrieţi programul. O linie logică este ceea ce vede Python ca o 
singură declaraţie. Python presupune implicit că fiecare linie fizică corespunde unei linii logice. 
Un exemplu de linie logică este o declaraţie 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ă (rând), ceea ce face 
codul mult mai lizibil. 
Dacă vreţi să specificaţi mai mult de o linie logică pe linie fizică, va trebui să specificaţi explicit 
încheierea liniei logice cu (;). De exemplu, 
i = 5
print(i)

este efectiv la fel ca 
i = 5;
print(i);

şi acelaşi lucru poate fi scris 
i = 5; print(i);

sau chiar 
i = 5; print(i)

Totuşi, recomand cu tărie să rămâneţi la scrierea cel mult a unei singure linii logice pe fiecare 
linie fizică. Prin folosirea mai multor linii logice pe o linie fizică se obţine realmente cod mai lung. 
Ideea este să se evite semnul punct şi virgulă la maxim posibil pentru a obţine un cod cât mai lizibil. 
De fapt, eu n­am folosit niciodată şi nici n­am văzut punct şi virgulă într­un program Python. 
Să dăm un exemplu de linie logică întinsă pe mai multe linii fizice, care se numeşte reunire 
explicită a liniilor. 
s = 'Acesta este un şir \
care continuă pe a doua linie.'
print(s)

Se obţine rezultatul: 
Acesta este un şir care continuă pe a doua linie.

Similar, 
print\
(i)

este la fel ca 
print(i)

20
Există şi reunire implicită a liniilor, conform unei prezumţii care elimină nevoia de backslash. Este 
cazul în care linia logică foloseşte paranteze rotunde, paranteze drepte sau acolade. Le veţi vedea în 
acţiune când vom scrie programe folosind liste în capitolele finale. 

Indentarea 
Spaţiul alb este important în Python. De fapt, spaţiul alb la începutul liniei este important. Acesta 
se numeşte indentare. Spaţiul alb (spaţii şi taburi) de la începutul liniei logice este folosit pentru a 
determina nivelul de indentare al liniei logice, care la rândul lui este folosit pentru a determina 
gruparea declaraţiilor. 
Asta înseamnă că declaraţiile care merg împreună trebuie să aibă aceeaşi indentare. Fiecare astfel 
de set de declaraţii se numeşte bloc. Vom vedea exemple despre importanţa blocurilor în capitolele 
următoare. 
Un lucru demn de reţinut este că indentarea greşită poate produce erori. De exemplu: 
i = 5
print('Valoarea este ', i) # Eroare! Observaţi un spaţiu la începutul liniei.
print('Repet, valoarea este ', i)

Când rulaţi asta, obţineţi următoarea eroare: 
File "whitespace.py", line 4
print('Valoarea este ', i) # Eroare! Observaţi un singur spaţiu la
începutul liniei.
^
IndentationError: unexpected indent

Observaţi că există un spaţiu la începutul liniei a doua. Eroarea indicată de Python ne spune că 
sintaxa este greşită, adică programul nu a fost scris corespunzător. Asta înseamnă că nu poţi începe 
în mod arbitrar noi blocuri de declaraţii ­ cu excepţia blocului principal[9] implicit pe care l­aţi 
folosit tot timpul. Cazurile în care puteţi folosi un nou bloc de declaraţii vor fi detaliate în capitolele 
finale, cum ar fi capitolul despre controlul execuţiei. 
Cum se indentează 
Nu folosiţi un amestec de SPACE şi TAB fiindcă programele nu vor lucra corect pe toate 
platformele. Vă recomand călduros să folosiţi un singur TAB sau patru spaţii pentru fiecare 
nivel de indentare. 
Alegeţi oricare din aceste stiluri de indentare. Şi mai important, alegeţi un stil şi folosiţi­l în 
mod consistent şi exclusiv. 

Notă pentru programatorii în limbaje cu tipuri statice 
Python va folosi mereu indentarea pentru blocuri şi niciodată acolade. Rulaţi from
__future__ import braces pentru a afla mai multe detalii. 

Rezumat 
Acum că am trecut prin multe detalii esenţiale, putem continua cu lucruri mai interesante cum ar fi 
declaraţii pentru controlul execuţiei. Asiguraţi­vă că aţi înţeles ce aţi învatat în acest capitol. 

21
22
Python ro:Operatori şi expresii

Introducere 
Majoritatea declaraţiilor (linii logice) pe care le scrieţi conţin expresii. Un exemplu de expresie 
simplă este 2 + 3. O expresie poate fi descompusă în operatori şi operanzi. 
Operatorii sunt functionalităţi care execută ceva şi pot fi reprezentaţi prin simboluri precum + sau 
prin cuvinte cheie speciale. Operatorii au nevoie de nişte date asupra cărora să opereze, numite 
operanzi. În acest caz, 2 şi 3 sunt operanzii. 

Operatori 
Vom arunca o privire rapidă asupra operatorilor şi a folosirii lor: 
Reţineţi că puteţi 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
>>>

Operatori şi folosirea lor

Operator  Nume  Explicaţie  Exemple 

3 + 5 fac 8
+  Plus  adună două obiecte 
'a' + 'b' fac 'ab'. 

fie face un număr să 
fie negativ fie dă  -5.2 face negativ numărul 5.2
­  Minus 
diferenţa între două  50 - 24 fac 26. 
numere 

dă produsul a două 
numere sau repetarea  2 * 3 fac 6
*  Inmulţire 
unui şir de numărul  'la' * 3 dă 'lalala'. 
specificat de ori 

23
3 ** 4 dă 81
**  Putere  dă x la puterea y 
(adică 3 * 3 * 3 * 3) 

/  Împărţire  împarte x la y  4 / 3 dă 1.3333333333333333. 

Împărţire  dă partea întreagă a 
//  4 // 3 fac 1. 
întreagă  câtului 

8 % 3 fac 2
%  Modulo  dă restul împărţirii 
-25.5 % 2.25 fac 1.5. 

Translateaza biţii unui 
număr la stânga cu 
numărul specificat de  2 << 2 da 8
Translaţie la  biţi. (Orice număr  2 este reprezentat prin 10 în biţi. Prin 
<< 
stânga  este reprezentat în  translaţie la stânga cu doi biţi se obţine 
memorie sub forma  1000 ceea ce reprezintă numărul 8. 
de biţi ­ cifre binare 0 
şi 1) 

Translateaza biţii  11 >> 1 dă 5


Translaţie la  numărului la dreapta  11 este reprezentat în biţi prin 1011
>> 
dreapta  cu numărul specificat  care translatat la dreapta cu un bit dă 
de biţi.  101 ceea ce reprezintă numărul 5. 

&  AND  ŞI binar între numere  5 & 3 da 1. 

SAU binar între 
|  OR  5 | 3 dă 7 
numere 

SAU exclusiv binar 
^  XOR  5 ^ 3 fac 6 
între numere 

Complement  complementul lui x 
~  ~5 dă -6. 
binar  este ­(x+1) 

24
Valoarea de adevăr a 
propoziţiei x este mai 
mic decât y. Toţi 
5 < 3 dă False
operatorii de 
3 < 5 dă True. 
Mai mic  comparaţie iau 

(decât)  valorile logice True
Comparaţiile pot fi înlănţuite arbitrar: 3
sau False. 
< 5 < 7 dă True. 
Observaţi că aceste 
nume încep cu 
majusculă. 

5 > 3 dă True. Dacă ambii operanzi 
Mai mare  Valoarea de adevăr a  sunt numere, aceştia sunt convertiţi întâi 

(decât)  propoziţiei x este mai  la un tip comun. În caz contrar operaţia 
mare decât y. ar avea mereu valoarea False. 

Valoarea de adevăr a 
Mai mic sau  propoziţiei x este mai 
<=  x = 3; y = 6; x <= y dă True. 
egal (cu)  mic sau cel mult egal 
cu y. 

Valoarea de adevăr a 
Mai mare sau  propoziţiei x este mai 
>=  x = 4; y = 3; x >= 3 da True. 
egal (cu)  mare sau cel puţin 
egal cu y. 

x = 2; y = 2; x == y dă True. 

x = 'str'; y = 'stR'; x ==
Verifică dacă două 
==  Egal (cu)  y dă False. 
numere sunt egale 
x = 'str'; y = 'str'; x ==
y dă True. 

Verifică dacă două 
numere sunt diferite 
!=  Diferit (de)  x = 2; y = 3; x != y dă True. 

25
dacă x este True, dă 
not  NU logic  False. Dacă x este  x = True; not x dă False. 
False, dă True. 

x = False; y = True; x and


y dă False întrucât x este False. În 
acest caz, Python nu va evalua pe y 
x and y dă False
fiindcă ştie că partea stângă a expresiei 
and  ŞI logic  dacă x este False, 
'and' este False ceea ce dă întregii 
altfel dă valoarea lui y 
expresii valoarea False indiferent de 
celelalte valori. Acest fapt se numeşte 
evaluare în circuit scurt. 

dacă x este True, dă  x = True; y = False; x or y


or  SAU logic  True, altfel dă  dă True. Şi aici se aplică evaluarea în 
valoarea lui y  circuit scurt. 

Prescurtare pentru operaţii matematice şi atribuiri 
Este uzual să faci o prelucrare matematică a unei variabile şi să păstrezi apoi rezultatul tot în ea; de 
aceea există o prescurtare pentru acest fel de expresii: 
În loc de: 
a = 2; a = a * 3

puteţi scrie: 
a = 2; a *= 3

Observaţi că var = var operaţie expresie devine var operaţie= expresie. 

Ordinea de evaluare 
Daca aveţi o expresie precum 2 + 3 * 4, se va evalua întâi operaţia de adunare sau cea de 
înmulţire? Matematica de liceu ne învaţă că multiplicarea ar trebui făcută întâi. Asta înseamnă că 
operatorul de înmulţire are precedenţă mai mare decât operatorul de adunare. 
Tabelul următor dă precedenţa operatorilor în Python, de la cea mai mică precedenţă (cea mai slabă 
legătură) până la cea mai mare precedenţă (cea mai strânsă legătură). Asta înseamnă că într­o 
expresie dată, Python va evalua întâi operatorii şi expresiile cele mai de jos în tabel înaintea celor 
mai de sus. 
Următorul tabel, extras din manualul de referinţe 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 precedenţa. Astfel programul devine mai lizibil. Pentru detalii vă rog să urmăriţi mai jos 
Schimbarea ordinii de evaluare. 

26
Precedenţa operatorilor 
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

<, <=, >, >=, !=, ==  Comparaţii 

|  SAU binar 

^  SAU­exclusiv binar 


ŞI binar

<<, >>  Translaţii 

+, ­ 
Adunare şi scădere

*, /, //, %  Înmulţire, împărţire, împărţire întreagă, modulo 

+x, ­x  Pozitiv, negativ 

~x  NU binar 

**  Exponenţiere 

27
x.atribut  Referinţă la atribut 

x[index] 
Referinţă la element

x[index1:index2]  Feliere 

f(argumente ...)  Apel la funcţie 

(expresii, ...)  Legătura sau afişarea unui cuplu 

[expresii, ...]  Afişarea unei liste 

{cheie:date, ...}  Afişarea unui dicţionar 

Operatorii pe care nu i­am întâlnit până acum vor fi descrişi în capitolele viitoare. 
Operatorii cu aceeaşi precedenţă sunt listaţi în acelaşi rând în tabelul anterior. De exemplu, + şi -
au aceeaşi precedenţă. 

Schimbarea ordinii de evaluare 
Pentru a face expresiile mai lizibile, putem folosi paranteze. De exemplu, 2 + (3 * 4) este în 
mod clar mai uşor de înţeles decât 2 + 3 * 4 care necesită cunoaşterea precedenţei operatorilor. 
Ca şi orice altceva, parantezele trebuie folosite cu discernământ (nu exageraţi) şi fără redundanţă (ca 
în 2 + (3 + 4)). 
Există un avantaj suplimentar în folosirea parantezelor ­ ne ajută să schimbăm ordinea de evaluare. 
De exemplu, dacă vreţi să fie evaluată adunarea înaintea înmulţirii întro expresie, trebuie să o scrieţi 
(2 + 3) * 4. 

Asociativitatea 
Operatorii sunt de obicei asociativi de la stânga la dreapta, adică operatorii cu aceeaşi precedenţă 
sunt evaluaţi de la stânga la dreapta. De exemplu, expresia 2 + 3 + 4 este evaluata ca (2 + 3)
+ 4. Câţiva operatori, precum atribuirea sunt asociativi de la dreapta la stânga astfel espresia a =
b = c este evaluată caa = (b = c). 

Expresii 
Exemplu: 
#!/usr/bin/python
# Fişier: expression.py

lungime = 5

28
lăţime = 2

aria = lungime * lăţime


print('Aria este', aria)
print('Perimetrul este', 2 * (lungime + lăţime))

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

Cum funcţionează: 
Lungimea şi lăţimea dreptunghiului sunt stocate în variabile cu numele respective. Le folosim 
pentru a calcula aria şi perimetrul dreptunghiului cu ajutorul expresiilor. Stocăm rezultatul expresiei 
lungime * lăţime în variabila aria şi o afişăm folosind funcţia print. În al doilea caz, 
folosim direct valoarea expresiei 2 * (lungime + lăţime) în funcţia print. 
De asemenea, observaţi cum Python 'cosmetizează' tipărirea rezultatului. Deşi noi n­am specificat 
un spaţiu între 'Aria este' şi variabila aria, Python o face pentru noi ca să obţinem o 
prezentare mai clară şi astfel programul este mult mai lizibil (fiindcă nu mai trebuie să ne îngrijim 
de spaţierea şirurilor folosite pentru afişare). Acesta este un exemplu despre cum face Python viaţa 
programatorului mai uşoară. 

Rezumat 
Am învăţat ce sunt operatorii, operanzii şi expresiile ­ acestea sunt componentele de bază ale 
oricarui program. În continuare vom vedea cum se folosesc în declaraţii. 

29
Python ro:Controlul execuţiei

Introducere 
În programele pe care le­am văzut până acum erau o serie de declaraţii şi Python le executa 
credincios în aceeaşi ordine. Dar dacă am fi vrut să schimbam fluxul sau modul lui de lucru? De 
exemplu, vreţi ca programul să ia nişte decizii şi să facă procesări diferite în diferite situaţii, precum 
a tipări 'Bună ziua' sau 'Bună seara' în funcţie de ora la care se execută programul? 
Cum poate aţi ghicit, asta se poate face cu declaraţii de control al execuţiei. Există trei declaraţii de 
control al execuţiei în Python ­ if, for şi while. 

Declaraţia if 
Declaraţia if este folosită pentru a testa o condiţie şi, dacă aceasta este adevărată, să ruleze un bloc 
de declaraţii (numit 'blocul if'), iar în caz contrar să ruleze alt bloc de declaraţii (blocul 'else'). 
Clauza 'else' este optională. 
Exemplu: 
#!/usr/bin/python
# Fişier: if.py

număr = 23
ghici = int(input('Introduceţi un întreg : '))

if ghici == număr:
print('Felicitări, aţi ghicit,') # Noul bloc începe aici
print('(dar nu câştigaţi niciun premiu!)') # Noul bloc se încheie aici

elif ghici < număr:


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ă ajungeţi aici e sigur ca ghici > număr

print('Gata')
# Aceasta ultimă declaraţie este executată întotdeauna, după declaraţia if

Rezultat: 
$ python if.py
Introduceţi un întreg : 50
Nu, e un pic mai mic.
Gata

$ python if.py
Introduceţi un întreg : 22
Nu, e un pic mai mare.
Gata

30
$ python if.py
Introduceţi un întreg : 23
Felicitări, aţi ghicit,
dar nu câştigaţi niciun premiu!
Gata

Cum funcţionează: 
În acest program preluăm de la utilizator încercări de a ghici numărul şi verificăm dacă este 
numărul memorat. Setăm variabila număr la ce valoare vrem, să zicem 23. Apoi preluăm numărul 
încercat de utilizator folosind funcţia input(). Funcţiile sunt nişte porţiuni de program 
reutilizabile. Vom afla mai multe despre ele în capitolul următor. 
Furnizăm un şir funcţiei implicite input() care îl tipăreşte pe ecran şi aşteaptă introducerea de 
informaţie de la utilizator. Îndată ce introducem ceva (ENTER ­ rom. a intra/introduce) şi apăsăm 
tasta ENTER, funcţia input() dă ca rezultat ceea ce am introdus, sub formă de şir. Convertim 
acest şir întrun întreg folosind declaraţia int şi stocăm valoarea în variabila ghici. De fapt int
este o clasă, dar ce trebuie să ştiţi în acest moment este că îl folosiţi pentru a converti un şir într­un 
întreg (presupunând că şirul conţine un întreg valid în text). 
În continuare comparăm alegerea utilizatorului cu numărul stabilit de noi. Dacă acestea sunt egale, 
tipărim un mesaj de succes. Observaţi că folosim nivele de indentare pentru a­i spune Pythonului 
cărui bloc aparţine fiecare declaraţie. Iată de ce este indentarea atat de importantă în Python. Sper 
că v­aţi ataşat de regula indentării consistente. Este aşa? 
Observaţi cum declaraţia if conţine semnul două puncte la sfârşit ­ aşa îi spunem Pythonului că 
urmează un bloc de declaraţii. 
Mai departe, testăm dacă numărul furnizat de utilizator este mai mic decât numărul şi, dacă este aşa, 
informşăm utilizatorul că trebuie să ţintească mai sus de atât. Ce am folosit aici este clauza elif
care de fapt combină două declaraţii if else-if else într­o singură declaraţie if-elif-
else. Asta face programul mai uşor şi reduce numărul de indentări necesar. 
Şi clauzele elif şi else trebuie să aibă la sfârşitul liniei logice semnul două puncte după care 
poate urma blocul lor de declaraţii (cu indentarea adecvată, desigur). 
Puteţi pune o altă declaraţie if în interiorul blocului 'if' al declaraţiei if s.a.m.d. ­ în acest caz 
declaraţiile if se numesc imbricate (engl. nested). 
Clauzele elif şi else sunt opţionale. O declaraţie if minimală este: 
if True:
print('Da, e adevarat.')

După ce Python a terminat execuţia întregii declaraţii if inclusiv clauzele elif şi else, el trece 
la următoarea declaraţie din blocul care conţine declaraţia if. În acest caz este vorba de blocul 
main (rom. principal), unde începe întotdeauna execuţia programului, iar instrucţiunea următoare 
este declaraţia print('Gata'). După aceasta, Python vede sfârşitul programului şi încheie. 
Deşi acesta este un program foarte simplu, am indicat o mulţime de lucruri care trebuie observate. 
Toate acestea sunt destul de directe (şi simple pentru cei care au cunoştinţe de C/C++) şi iniţial 
necesită să deveniţi constienţi de ele, dar apoi vor deveni uzuale şi vă vor părea 'naturale'. 
Notă pentru programatorii în C/C++ 
Nu există declaraţia switch în Python. Puteţi utiliza declaraţia if..elif..else pentru a 
face acelaşi lucru (şi în unele cazuri, puteţi folosi o structură de date pentru a rezolva repede). 

31
Declaraţia while 
Declaraţia while ne permite să executăm repetat un bloc de declaraţii atât timp cât o condiţie 
rămâne adevărată. O declaraţie while este un exemplu de instrucţiune de ciclare. Poate avea şi 
clauza else. 
Exemplu: 
#!/usr/bin/python
# Fişier: while.py

număr = 23
ciclu = True

while ciclu:
ghici = int(input('Introduceţi un întreg : '))

if ghici == număr:
print('Felicitări, aţi ghicit!')
ciclu = False # asta face ciclul să se întrerupă
elif ghici < număr:
print('Nu, este puţin mai mare.')
else:
print('Nu, este puţin mai mic..')
else:
print('Bucla s-a încheiat.')
# Aici puteţi face ce prelucrări vreţi

print('Gata')

Rezultat: 
$ python while.py
Introduceţi un întreg : 50
Nu, este puţin mai mic.
Introduceţi un întreg : 22
Nu, este puţin mai mare
Introduceţi un întreg : 23
Felicitări, aţi ghicit.
Bucla s-a încheiat.
Gata

Cum funcţionează: 
În acest program jucăm tot jocul cu ghicirea numărului, dar avantajul este ca utilizatorul poate 
continua încercările până când ghiceşte ­ nu trebuie să ruleze programul de fiecare dată, cum am 
facut în programul precedent. Ceea ce este chiar o demostraţie de declaraţie while. 
Deplasăm declaraţiile input şi if în interiorul buclei while şi iniţializăm variabila ciclu cu 
True înaintea buclei. La început testăm dacă variabila ciclu este True şi apoi continuăm cu 
executarea blocului while. După ce blocul a fost executat, condiţia este evaluată din nou şi, în acest 
caz, condiţia este variabila ciclu. Dacă este True, executăm blocul while din nou, altfel 
verificăm dacă există o clauză else ca s­o executăm. 
Blocul else este executat atunci cand condiţia de ciclare devine False ­ asta poate fi chiar şi 
prima dată când se testează condiţia. Dacă exista un bloc else la bucla while, ea va fi 
întotdeauna executată, dacă nu se iese forţat din buclă cu o declaraţie break. 

32
Valorile True şi False sunt numite booleene şi pot fi considerate a fi echivalente cu valorile 1 şi 
respectiv 0. 
Notă pentru programatorii în C/C++ 
Reţineţi că poate exista o clauză else la bucla while. 

Bucla for 
Declaraţia for..in este o declaraţie de ciclare care iterează elementele unei secvenţe de obiecte. 
Vom afla mai multe despre secvenţe în capitolele următoare. Ce trebuie ştiut acum este că o 
secvenţă este pur şi simplu o colecţie ordonată de elemente. Exemplu: 
#!/usr/bin/python
# Fişier: 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 funcţionează: 
În acest program, tipărim o secvenţă de numere. Generăm secvenţa cu ajutorul funcţiei predefinite 
range. 
Noi dăm funcţiei range două numere şi ea ne dă secvenţa de numere începând cu primul număr şi 
până la cel de­al doilea. De exemplu, range(1,5) înseamnă secvenţa [1, 2, 3, 4]. Implicit, 
range are pasul 1. Dacă îi dăm şi un al treilea număr, range acela devine pasul secvenţei. De 
exemplu range(1,5,2) dă [1,3]. Reţineţi că gama de numere (engl. range) se extinde până la 
al doilea număr, dar nu' îl şi include. 
Aşadar 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 
rând, şi executarea blocului de declaraţii pentru fiecare valoare a lui i. În acest caz, nu facem 
altceva decât să tipărim valoarea obiectului. 
Amintiţi­vă că clauza else este opţională. Când este inclusă, este executată întotdeauna o dată, 
după încheierea buclei for, cu excepţia cazului în care se întâlneşte o declaraţie break. 
De reţinut că bucla for..in funcţionează pentru orice secvenţă. În acest caz avem doar o listă de 
numere, generată cu funcţia 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 
reţine că bucla for din Python este similară cu bucla foreach din C#. Programatorii Java 

33
să observe că acelaşi 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). Aşa cum vedeţi, în Python bucla for este mai simplă, mai 
expresivă şi mai puţin predispusă la erori. 

Declaraţia break 
Declaraţia break este folosită pentru a întrerupe (engl. break) executarea unei declaraţii de ciclare, 
chiar şi dacă condiţia testată nu a devenit încă False sau secvenţa 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
# Fişier: break.py

while True:
s = (input('Introduceţi ceva:'))
if s == 'quit':
break
print('Lungimea şirului introdus este', len(s))
print('Gata')

Rezultat: 
$ python break.py
Introduceţi ceva: Programarea e mişto
Lungimea şirului introdus este 15
Introduceţi ceva: Când treaba e facută
Lungimea şirului introdus este 20
Introduceţi ceva: Dacă vrei să te şi distrezi:
Lungimea şirului introdus este 27
Introduceţi ceva: foloseşte Python!
Lungimea şirului introdus este 17
Introduceţi ceva: quit
Gata

Cum funcţionează: 
În acest program, preluăm datele de intrare în mod repetat de la utilizator şi tipărim lungimea 
fiecărui şir introdus. Prevedem şi o condiţie specială pentru oprirea programului, prin căutarea 
cuvântului 'quit'. Oprim programul prin întreruperea buclei şi ajungerea la sfârşitul blocului de 
declaraţii. 
Lungimea şirului de intrare poate fi găsită folosind funcţia predefinită len. 
Reţineţi că declaraţia break poate fi folosită şi cu declaraţia for. 

Poezia lui Swaroop despre Python 
Ce am folosit aici drept intrare (de la utilizator) este un mini poem scris de mine, numit Swaroop's 
Poetic Python (în limba engleză): 
Programming is fun

34
When the work is done
if you wanna make your work also fun:
use Python!

Declaraţia continue 
Declaraţia continue se foloseşte pentru a spune lui Python să treacă la următoarea iteraţie fără să 
execute instrucţiunile rămase din blocul declaraţiei de ciclare. 
Exemplu: 
#!/usr/bin/python
# Fişier: continue.py

while True:
s = input('Introduceţi ceva: ')
if s == 'quit':
break
if len(s) < 3:
print('Prea puţin')
continue
print('Şirul introdus are lungime suficientă')
# Faceţi alte procesări aici...

Rezultat: 
$ python test.py
Introduceţi ceva: a
Prea puţin
Introduceţi ceva: 12
Prea puţin
Introduceţi ceva: abc
Şirul introdus are lungime suficientă
Introduceţi ceva: quit

Cum funcţionează: 
În acest program acceptăm date de la utilizator, dar le procesăm doar dacă au cel puţin 3 caractere 
lungime. Aşadar, folosim funcţia len pentru a obţine lungimea şi, dacă aceasta este mai mică decât 
3, sărim peste ce a mai rămas din iteraţia curentă folosind declaraţia continue. În caz contrar, 
restul declaraţiilor din buclă sunt executate şi putem să facem orice fel de procesare în zona unde 
este acel comentariu. 
Retineţi că declaraţia continue funcţionează şi cu bucla for. 

Rezumat 
Am văzut cum se folosesc cele trei instrucţiuni de control al execuţiei ­ if, while şi for
împreună cu asociatele lor, declaraţiile break şi continue. Acestea sunt unele dintre cele mai 
utilizate părţi din Python şi de aceea este esenţial să te obişnuieşti cu ele. 
În continuare vom învăţa să construim şi să folosim funcţii. 

35
Python ro:Funcţii

Introducere 
Funcţiile sunt porţiuni de program reutilizabile. Ele vă permit să daţi nume unui bloc de declaraţii şi 
puteţi rula acel bloc de declaraţii în program de câte ori vreţi. Asta se numeşte apel al funcţiei. Noi 
am folosit deja multe funcţii predefinite precum len şi range. 
Conceptul de funcţie este probabil cel mai important bloc constructiv al oricărui program nonbanal 
(în orice limbaj de programare), deci vom explora diverse aspecte ale funcţiilor în acest capitol. 
Funcţiile sunt definite folosind cuvântul cheie def. Acesta este urmat de un nume identificator 
pentru funcţie urmat de o pereche de paranteze care pot include nişte nume de variabile. În 
continuare este plasat blocul de declaraţii care compun funcţia. Un exemplu va arăta cât este de 
simplu: 
Exemplu: 
#!/usr/bin/python
# Fişier: function1.py

def sayHello():
print('Hello World!') # blocul funcţiei
# Sfârşitul funcţiei

sayHello() # apel la funcţia sayHello()


sayHello() # din nou apel la funcţia sayHello()

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

Cum funcţionează: 
Definim o funcţie numită sayHello folosind sintaxa explicată mai sus. Aceasta funcţie nu 
primeşte parametri şi deci nu sunt declarate variabile în paranteze. Parametrii pentru funcţie sunt 
doar nişte modalităţi de a­i transmite funcţiei diferite valori sau/şi de a extrage valorile 
corespunzătoare. 
Observaţi că putem apela aceeaşi funcţie de două ori, ceea ce înseamnă că nu mai trebuie să scriem 
aceeaşi porţiune de cod din nou. 

Parametrii funcţiilor 
O funcţie poate accepta parametri, care sunt valori furnizate funcţiei pentru ca aceasta să poată face 
ceva cu aceste valori. Aceşti parametri sunt ca variabilele numai că valorile acestor variabile sunt 
definite în momentul apelului funcţiei şi deja le sunt atribuite valori la momentul executării blocului 
funcţiei. 

36
Parametrii sunt specificaţi într­o pereche de paranteze în definiţia funcţiei, separate prin virgule. 
Când apelăm funcţia, furnizăm aceste valori într­un fel sau altul. Observaţi terminologia folosită ­ 
numele date în funcţie se numesc parametri în timp ce valorile pe care le furnizăm în apelul funcţiei 
se numesc argumente. 
Exemplu: 
#!/usr/bin/python
# Fişier: 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 funcţionează: 
Aici definim o funcţie numită printMax care primeşte doi parametri numiţi a şi b. Găsim cel mai 
mare număr dintre ele folosind o simpla declaraţie if..else şi tipărim pe ecran cel mai mare 
număr. 
În primul apel al funcţiei printMax, furnizăm argumentele în forma literală. În al doilea apel dăm 
funcţiei 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. 
Funcţia printMax lucrează la fel în ambele cazuri. 

Variabile locale 
Când se declară variabile în interiorul definiţiei funcţiei, acestea nu au nici un fel de legătură cu alte 
variabile din afara definiţiei funcţiei, nici chiar dacă ar avea acelaşi nume, de aceea se numesc 
variabile locale funcţiei. Acesta este domeniul variabilei. Toate variabilele au ca domeniu blocul în 
care sunt declarate, începând cu punctul în care a fost definit numele ei. 
Exemplu: 
#!/usr/bin/python
# Fişier: func_local.py

x = 50

def func(x):

37
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 funcţionează: 
În funcţie, prima dată când folosim valoarea numelui x, Python foloseşte valoarea parametrului 
declarat în funcţie. 
În continuare atribuim valoarea 2 lui x. Numele x este local funcţiei noastre. Prin urmare, când 
schimbăm valoarea lui x în funcţie, x definit în blocul principal rămâne neafectat. 
În ultimul apel al funcţiei print, afişăm valoarea lui x din blocul principal ca să confirmăm că a 
rămas neafectată. 

Folosirea declaraţiei global 
Dacă vreţi să atribuiţi o valoare unui nume definit la nivelul cel mai înalt al programului (adică nu 
în interiorul domeniului funcţiei sau clasei), va trebui să­i spuneţi lui Python că acel nume nu este 
local ci global. Obţinem asta folosind declaraţia global. Este imposibil ca în interiorul unei 
funcţii să atribui o valoare unei variabile definite în afara funcţiei fără declaraţia global. 
Puteţi folosi valorile definite în afara funcţiilor (presupunând că nu există o variabilă cu acelaşi 
nume definită în blocul funcţiei). Totuşi, acest fapt nu este încurajat şi trebuie evitat întrucât devine 
neclar cititorului unde este definiţia acelei variabile. Folosind declaraţia global marcăm foarte 
clar că variabila este definită în cel mai exterior bloc. 
Exemplu: 
#!/usr/bin/python
# Fişier: 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

38
x este 50
Am schimbat x global în 2
Valoarea lui x este 2

Cum funcţionează: 
Declaraţia global este folosită pentru a declara că x este o variabilă globală ­ de aceea, când 
atribuim o valoare lui x în interiorul funcţiei, acea schimbare se reflectă când folosim valoarea lui x
în blocul principal. 
Puteţi specifica mai multe variabile globale folosind declaraţia global. De exemplu, global x,
y, z. 

Folosirea declaraţiei nonlocal 
Am învăţat să accesăm variabile în domeniul local şi global. Mai există un domeniu specific 
funcţiilor, numit "nonlocal" şi care se află între cele două. Domeniile nonlocal se observă când 
definiţi funcţii în interiorul funcţiilor. 
Întrucât totul în Python este cod executabil, se pot defini funcţii oriunde. 
Să luăm un exemplu: 
#!/usr/bin/python
# Fişier: 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 funcţionează: 
Când ne aflăm în interiorul unei funcţii func_inner, 'x' definit în prima linie a funcţiei 
func_outer este undeva între global şi local. Declarăm că folosim acest x cu declaraţia 
nonlocal x şi astfel obţinem acces la acea variabilă. 
Încercaţi să schimbaţi nonlocal x cu global x şi să eliminaţi complet declaraţia, ca să vedeţi 
ce diferenţe de comportament sunt în aceste cazuri. 

39
Valori implicite ale argumentelor 
Pentru unele funcţii, poate vreţi să faceţi unii parametri opţionali şi să folosiţi valori implicite în 
cazul în care utilizatorul nu furnizează o valoare pentru parametrul respectiv. Asta se face cu 
ajutorul valorilor implicite ale parametrilor. Puteţi specifica valorile implicite ale argumentelor în 
definiţia funcţiei, punând operatorul de atribuire (=) urmat de valoarea implicită. 
Observaţi 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 următoare. Pentru moment reţineţi doar 
atât. 
Exemplu: 
#!/usr/bin/python
# Fişier: func_default.py

def say(mesaj, ori = 1):


print(mesaj * ori)

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

Rezultat: 
$ python func_default.py
Hello
WorldWorldWorldWorldWorld

Cum funcţionează: 
Funcţia numită say este folosită pentru a tipări pe ecran un şir de atâtea ori cât se specifică. Dacă 
nu furnizăm acea valoare, atunci va fi folosită valoarea implicită, 1. Obţinem aceasta punând 
valoarea implicită 1 a parametrului ori. 
La prima folosire a funcţiei say, dăm numai şirul şi ea îl tipăreşte o dată. În a doua folosire dăm 
funcţiei say şi şirul şi un argument 5 ceea ce spune că vrem să fie tipărit şirul de 5 ori. 
Important 
Numai parametrii de la sfârşitul listei de parametri pot avea valori implicite deci nu puteţi avea 
un parametru cu valoare implicită înaintea altuia fără valoare implicită în lista de parametri a 
funcţiei. 
Motivul este că valorile sunt atribuite parametrilor prin poziţie. De exemplu, def func(a,
b=5) este validă, dar def func(a=5, b) este invalidă. 

Argumente cuvânt cheie 
Dacă aveţi funcţii cu mulţi parametri şi vreţi să specificaţi numai pe unii, atunci puteţi să daţi valori 
parametrilor prin numele lor ­ acest mod de specificare se numeşte prin argumente cuvânt cheie ­ 
folosim cuvântul cheie (engl. keyword) în locul poziţiei (pe care am folosit­o până acum) pentru a 
specifica argumente funcţiei. 
Există două avantaje ­ unu, folosirea funcţiei este mai uşoară, întrucât nu trebuie să ne preocupăm 
de ordinea parametrilor. Doi, putem da valori numai unor parametri selectaţi, cu condiţia ca toţi 
ceilalţi sa aibă în definiţia funcţiei valori implicite. 

40
Exemplu: 
#!/usr/bin/python
# Fişier: 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 funcţionează: 
Funcţia numită func are un parametru fără valoare implicită, urmat de doi parametri cu valori 
implicite. 
În primul apel, func(3, 7), parametrul a primeşte valoarea 3, parametrul b primeşte valoarea 
7, iar c valoarea implicită, 10. 
În al doilea apel, func(25, c=24), variabila a ia valoarea 25 datorită poziţiei argumentului. Pe 
urmă, parametrul c ia valoarea 24 prin nume ­ argument cuvânt cheie. Variabila b ia valoarea 
implicită, 5. 
În al treilea apel, func(c=50, a=100), folosim numai tehnica nouă, a cuvintelor cheie. 
Observaţi, specificăm valoarea parametrului c înaintea parametrului a deşi a este definit înaintea 
variabilei c în definiţia funcţiei. 

Parametri VarArgs 
TODO 
Să scriu despre asta într­un capitol următor, fiindcă nu am vorbit încă despre liste şi 
dicţionare? 

Uneori aţi putea dori să definiţi o funcţie care să ia orice număr de parametri, asta se poate face 
folosind asteriscul: 
#!/usr/bin/python
# Fişier: total.py

def total(iniţial=5, *numere, **keywords):


numărător = iniţial
for număr in numere:
numărător += număr
for cheie in keywords:
numărător += keywords[cheie]
return numărător

print(total(10, 1, 2, 3, legume=50, fructe=100))

41
Rezultat: 
$ python total.py
166

Cum funcţionează: 
Când declarăm un parametru cu asterisc precum *parametri, toţi parametrii poziţionali de la 
acel punct încolo sunt colectaţi întro listă numită 'parametri'. 
Similar, când declarăm un parametru cu două asteriscuri, precum **parametri, toate 
argumentele cuvânt cheie de la acel punct încolo sunt colectate într­un dicţionar numit 'parametri'. 
Vom explora listele şi dicţionarele întrun capitol următor. 

Parametri exclusiv cuvânt cheie 
Dacă vrem să specificăm anumiţi parametri cuvânt cheie pentru a fi disponibili numai în forma 
cuvânt cheie şi niciodată ca parametri poziţionali, aceştia pot fi declaraţi după un parametru cu 
asterisc: 
#!/usr/bin/python
# Fişier: keyword_only.py

def total(iniţial=5, *numere, legume):


numărător = iniţial
for număr in numere:
numărător += număr
numărător += legume
return numărător

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 funcţionează: 
Declararea de parametri după un parametru cu asterisc (engl. starred parameter) produce argumente 
exclusiv cuvânt cheie. Dacă acestea nu sunt definite cu valori implicite, apelurile funcţiei vor ridica 
o eroare dacă nu se furnizează argumentul cuvânt cheie, aşa cum s­a văzut mai sus. 
Dacă vreţi să aveţi parametri exclusiv cuvânt cheie, dar nu aveţi nevoie de nici un parametru cu 
asterisc, folosiţi un asterisc izolat, ca în exemplul: 
def total(iniţial=5, *, legume). 

42
Declaraţia return 
Declaraţia return este folosită pentru a ne întoarce dintr­o funcţie (deci a evada din ea ­ engl. 
break out). Opţional putem întoarce o valoare la fel de bine. 
Exemplu: 
#!/usr/bin/python
# Fişier: 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 funcţionează: 
Funcţia maximum întoarce parametrul cel mai mare furnizat funcţiei. Ea foloseşte o declaraţie 
simplă if..else pentru a găsi numărul cel mai mare şi apoi întoarce (engl. return) acea valoare. 
Observaţi că declaraţia return fără 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 funcţie, în mod implicit, conţine o declaraţie return None la sfârşitul blocului de 
declaraţii, cu excepţia cazului în care îi scrieţi o altă declaraţie return. Puteţi vedea asta rulând 
print o_funcţie_oarecare() în care nu este dată o declaraţie return precum: 
def o_functie_oarecare():
pass

Declaraţia pass este folosită în Python pentru a indica un bloc de declaraţii gol. 
Notă 
Există o funcţie predefinită numită max care implementează această funcţionalitate de a 'găsi 
maximul', deci folosirea aceste funcţii este posibilă oricand. 

DocStrings 
Python are o facilitate drăguţă numită documentation strings, numită de obicei pe numele scurt 
docstrings. DocStrings (rom. şiruri de documentaţie, sg. docstring) sunt o unealtă importantă pentru 
că vă ajută să documentaţi programele mai bine şi le face mai uşor de înţeles. Uimitor, putem chiar 
să extragem şirurile de documentare ale, să zicem, unei funcţii chiar în timp ce programul rulează! 
Exemplu: 
#!/usr/bin/python
# Fişier: func_doc.py

43
def printMax(x, y):
'''Tipăreşte pe ecran cel mai mare din două numere.

Cele două numere trebuie să fie întregi.'''


x = int(x) # converteşte î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
Tipăreşte pe ecran cel mai mare din două numere.

Cele două numere trebuie să fie întregi.


5 este maximum

Cum funcţionează: 
Un şir pe prima linie logică a funcţiei devine docstring pentru acea funcţie. De retinut că DocStrings 
se aplică şi la module şi clase, despre care vom învăţa în capitolele respective. 
Convenţia 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 explicaţie mai detaliată începand 
cu linia a treia. Vă sfătuim cu căldură să urmaţi aceasta convenţie pentru toate docstringurile tuturor 
funcţiilor nebanale pe care le scrieţi. 
Putem accesa docstringul funcţiei printMax folosind atributul __doc__ (observaţi dublu 
underscore) al funcţiei. Amintiţi­vă că Python tratează totul ca obiect, inclusiv funcţiile. Vom învăţa 
mai mult despre obiecte în capitolul despre clase. 
Daca aţi folosit help() în Python, aţi văzut deja cum se foloseşte docstring! Ceea ce face ea este 
că extrage atributul __doc__ al funcţiei şi îl afişează într­o maniera convenabilă. Puteţi încerca 
asta asupra funcţiei de mai sus ­ includeţi pur şi simplu declaraţia help(printMax) în program. 
Nu uitaţi să tastaţi q pentru a ieşi din help. 
Utilitarele pot colecta automat documentaţia din programe în această maniera. De aceea vă 
recomand insistent să folosiţi docstring pentru orice funcţie nebanală pe care o scrieţi. Comanda 
pydoc inclusă în distribuţia Python funcţionează similar cu help() folosind docstringurile. 

Adnotări 
Funcţiile mai au o facilitate avansată numită adnotare (engl. annotations) care este o cale deşteaptă 
de a ataşa informaţie pentru fiecare din parametri precum şi pentru valoarea întoarsă. Întrucât 
limbajul Python în sine nu interpretează aceste adnotări în nici un fel (această funcţionalitate este 
lăsată bibliotecilor third­party să interpreteze ele în ce fel vor), vom trece peste această facilitate în 
discuţia noastră. Dacă sunteţi interesaţi despre adnotări, puteţi citi PEP No. 3107. 

44
Rezumat 
Am discutat multe aspecte ale funcţiilor, dar reţineţi că nu am acoperit toate aspectele posibile. 
Totuşi, 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. 

45
Python ro:Module

Introducere 
Aţi văzut cum se poate refolosi o porţiune de cod în program prin definirea funcţiilor. Dar dacă vreţi 
să refolosiţi un număr mai mare de funcţii în alte programe decât cel pe care îl scrieţi? Aşa cum aţi 
ghicit, răspunsul este folosirea modulelor. 
Există variate metode de a scrie module, dar cea mai simplă cale este de a crea un fişier cu extensia 
.py care conţine funcţii şi variabile. 
Altă metodă este scrierea modulelor în limbajul în care chiar interpretorul Python a fost scris. De 
exemplu, puteţi scrie module în limbajul de programare C şi dupa compilare, ele pot fi folosite din 
codul Python când se foloseşte interpretorul Python standard. 
Un modul poate fi importat de un alt program pentru a folosi funcţionalitatea acestuia. Aşa putem şi 
noi să folosim biblioteca standard Python. Întâi vom vedea cum se folosesc modulele bibliotecii 
standard. 
Exemplu: 
#!/usr/bin/python
# Fişier: 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\\plat-win',
'C:\\Python30', 'C:\\Python30\\lib\\site-packages']

Cum funcţionează: 
La început importăm modulul sys folosind declaraţia import. În esenţă, asta îi spune lui Python 
că vrem să folosim acest modul. Modulul sys conţine funcţionalitate legată de interpretorul Python 
şi mediul său, system. 
Când Python execută declaraţia import sys, el caută modulul sys. În acest caz, este vorba de 
un modul preinstalat şi de aceea Python ştie unde să­l găsească. 

46
Dacă nu ar fi fost un modul compilat, ci un modul scris în Python, interpretorul ar fi căutat în 
directoarele listate în variabila sys.path. Dacă modulul este găsit, declaraţiile din interiorul 
modului sunt executate. Observaţi că această iniţializare este făcută numai prima dată când 
importăm un modul. 
Variabila argv din modulul sys este accesată folosind notaţia cu puncte, adică sys.argv. Ea 
arată clar că acest nume este parte a modulului sys. Alt avantaj al acestei abordări 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 conţine lista argumentelor din linia de comandă adică acele 
argumente transmise programului prin adăugarea lor la linia de comandă care lansează programul. 
Daca folosiţi un IDE pentru a scrie şi rula aceste programe, căutaţi în meniuri o cale de a specifica 
argumente la linia de comandă. 
Aici, când se execută python using_sys.py noi suntem argumente, rulăm modulul 
using_sys.py cu comanda python şi celelalte lucruri care îl urmează sunt transmise 
programului. Python păstrează linia de comandă în variabila sys.argv ca să le putem folosi. 
Reţineţi, numele scriptului care rulează este întotdeauna primul argument din lista sys.argv. 
Deci în acest caz vom avea 'using_sys.py' în poziţia sys.argv[0], 'noi' în poziţia 
sys.argv[1], 'suntem' în poziţia sys.argv[2] şi 'argumente' în poziţia 
sys.argv[3]. Observaţi că Python începe numerotarea cu 0 nu cu 1. 
Variabila sys.path conţine lista numelor de director de unde pot fi importate module. Observaţi 
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 
prevăzut pentru a permite importul direct al modulelor aflate în directorul curent. În caz contrar 
modulele care trebuie importate trebuie poziţionate într­unul din directoarele listate în sys.path. 

Fisiere .pyc compilate in octeti 
Importul unui modul este relativ costisitor, astfel că Python face nişte smecherii ca să îl accelereze. 
O cale este să creeze fişiere compilate în octeţi (engl. byte­compiled) cu extensia .pyc care sunt 
nişte forme intermediare în care Python transformă programul (vă amintiţi din capitolul introductiv 
cum lucrează Python?). Acest fişier .pyc este util când importaţi un modul a doua oară din alte 
programe ­ ele vor fi mult mai rapide întrucât partea de procesare legată de importul modulului este 
deja realizată. De asemenea, aceste fişiere compilate în octeţi sunt independente de platformă. 
Notă 
Fişierele .pyc sunt create de obicei în acelaşi director ca şi fişierul .py corespondent. Dacă 
Python nu are permisiunea de a scrie fişiere în acel director, fişierele .pyc nu vor fi create. 

Declaraţia from ... import ... 
Dacă vreţi să importaţi direct variabila argv în programul vostru (pentru a evita scrierea numelui 
sys. de fiecare dată), puteţi folosi declaraţia from sys import argv. Dacă vreţi să 
importaţi toate numele folosite în modulul sys atunci puteţi folosi declaraţia from sys import
*. Funcţionează pentru orice modul. 

47
În general, trebuie să evitaţi folosirea acestor declaraţii şi în schimb să folosiţi declaraţia import. 
Ca să fie evitate orice conflicte de nume şi programele să fie mai lizibile. 

Atributul __name__ al modulului 
Orice modul are un nume, iar declaraţiile din modul pot găsi numele modulului. Este comod aşa, 
mai ales în situaţia particulară în care se doreşte aflarea regimului modulului (autonom sau 
importat). Cum am menţionat anterior, când 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 lăsa neschimbat dacă modulul este importat din alt 
modul. Acestea sunt posibile folosind atributul __name__ al modulului. 
Exemplu: 
#!/usr/bin/python
# Fişier: 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 funcţionează: 
Orice modul Python are propriul atribut __name__ definit şi dacăş acesta este '__main__', 
rezultă că acel modul este rulat de sine stătător de către utilizator şi putem lua măsurile adecvate. 

Crearea propriilor module 
Crearea propriilor noastre module este uşoară, aţi făcut asta tot timpul! Asta din cauză că orice 
program Python este un modul. Trebuie doar să ne asigurăm că fişierul are extensia .py. Următorul 
exemplu ar trebui să clarifice situaţia. 
Exemplu: 
#!/usr/bin/python
# Fişier: meu.py

def zisalut():
print('Salut, aici este modulul meu.')

__versiune__ = '0.1'

# Sfârşitul modulului meu.py

48
Mai sus a fost un model de modul. Aşa cum vedeţi, nu este nimic deosebit în legătură cu modulele 
în comparaţie cu programele Python obişnuite. Vom vedea în continuare cum putem să folosim 
acest modul în programele noastre Python. 
Amintiţi­vă că modulul ar trebui plasat în acelaşi director cu programul care îl importă sau într­un 
director listat în variabila sys.path. 
#!/usr/bin/python
# Fişier: 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 funcţionează: 
Observaţi că folosim aceeaşi notaţie cu punct pentru a accesa membrii modulului. Python 
refoloseşte cu spor aceeaşi notaţie pentru a da un sentiment distinctiv 'Pythonic' programelor, astfel 
încât să nu fim nevoiţi să învăţăm noi moduri de a face lucrurile. 
Iată o nouă variantă folosind sintaxa declaraţiei from..import: 
#!/usr/bin/python
# Fişier: meu_demo2.py

from meu import zisalut, __versiune__

zisalut()
print('Versiunea', __versiune__)

Rezultatul programului meu_demo2.py este acelaşi ca şi rezultatul programului meu_demo.py. 
Observaţi că dacă ar fi existat un nume __versiune__ declarat în modulul care importă modulul 
meu, ar fi apărut un conflict. Şi asta este probabil, întrucât este o practică uzuală pentru fiecare 
modul să se declare versiunea sa folosind acest nume. De aceea este întotdeauna recomandabil să se 
folosească declaraţia import deşi 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 decât implicit". Rulaţi import
this pentru a afla mai multe şi urmăriţi această discuţie care enumeră exemple pentru 
fiecare din principii. 

49
Funcţia dir 
Puteţi folosi funcţia predefinită dir pentru a lista identificatorii pe care îi defineşte un obiect. De 
exemplu, pentru un modul, clasele şi variabilele definite în acel modul. 
Când furnizaţi un nume funcţiei dir(), ea întoarce lista numelor definite în acel modul. Dacă se 
lansează funcţia fără argumente, ea întoarce lista numelor definite în modulul curent. 
Exemplu: 
$ python

>>> import sys # obţine 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() # obţine 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 funcţionează: 
Pentru început, vedem folosirea funcţiei dir asupra modulului importat sys. Putem vedea lista 
uriaşă de atribute pe care o conţine. 
Apoi folosim dir fără parametri. Implicit, ea întoarce lista atributelor modulului curent. Observaţi 
că lista modulelor importate este inclusă în lista modulului listat. 
Pentru a vedea funcţia dir în acţiune, definim o nouă variabilă, a, şi îi atribuim o valoare, apoi 
testăm cu dir dacă a apărut încă o valoare în lista de atribute a aceluiaşi nume. Eliminăm 
variabila/atributul modulului curent folosind declaraţia del şi din nou schimbarea este reflectată în 
rezultatul funcţiei dir. 
O notă asupra declaraţiei del ­ această declaraţie este folosită pentru a şterge un nume de variabila 
şi după ce a fost executată (del a), nu mai puteţi accesa variabila a ­ este ca şi cum nu a existat 

50
niciodată. 
Reţineţi că funcţia dir() lucrează pe orice obiect. De exemplu, rulaţi dir(print) pentru a 
descoperi atributele funcţiei print sau dir(str) pentru atributele clasei str. 

Pachete 
La acest nivel, aţi început probabil să observaţi o ierarhie în organizare a programelor. Variabilele 
sunt de obicei în interiorul funcţiilor. Funcţiile şi variabilele globale intră în module. Dar modulele 
cum se organizează? Aici intervin pachetele. 
Pachetele sunt nişte foldere de module cu un fişier special __init__.py care indică lui Python că 
acel folder este special, deoarece conţine module Python. 
Să zicem că vreţi să creaţi un pachet numit 'mapamond' cu subpachetele 'asia', 'africa', etc. şi aceste 
pachete conţin la rândul lor module precum 'india', 'madagascar', 'românia' etc. 
Iată cum aţi 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
- românia/
- __init__.py
- foo_bar.py

Pachetele sunt doar un mod convenabil de a organiza ierarhic modulele. Veţi vedea de multe ori asta 
în biblioteca Python standard. 

Rezumat 
Aşa cum funcţiile sunt părţi 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 văzut cum se folosesc modulele şi cum se creeaza module proprii. 
În continuare vom învăţa despre câteva concepte interesante numite 'structuri de date'. 

51
Python ro:Structuri de date

Introducere 
Structurile de date sunt în esenţă exact asta ­ structuri care pot memora date grupate. Cu alte 
cuvinte, sunt folosite pentru a stoca colecţii de date înrudite. 
Există patru structuri predefinite în Python ­ liste, tupluri, dicţionare şi seturi. Vom învăţa să le 
folosim pe fiecare şi cum ne pot uşura ele viaţa. 

Liste 
O listă (engl. list) este o structură de date care păstrează o colecţie ordonată de elemente deci se 
poate memora o secvenţă de elemente întro listă. Asta este uşor de imaginat dacă ne gândim la o 
listă de cumpărături, numai că pe listă fiecare item ocupă un rând separat, iar în Python punem 
virgule intre ele. 
Elementele listei trebuie incluse în paranteze drepte astfel încât Python să înţeleagă că este o 
specificare de listă. Odată ce am creat lista, putem adăuga, şterge sau căuta 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 
Deşi în general am amânat discutarea obiectelor şi claselor pâna acum, este necesară o scurtă 
introducere, pentru a se putea înţelege listele mai bine. Detaliile le vom afla în capitolul dedicat 
acestora. 
O listă este un exemplu de utilizare a obiectelor şi claselor. Când folosim o variabilă i şi îi atribuim 
o valoare, să zicem întregul 5, putem gândi că am creat un obiect (de fapt instanţă) i din clasa (de 
fapt tipul) int. De fapt se poate citi help(int) pentru o înţelegere mai aprofundatată. 
O clasă poate avea şi metode adică funcţii definite pentru a fi folosite exclusiv în raport cu acea 
clasă. Puteţi folosi aceste funcţionalităţi numai asupra unui obiect din acea clasă. De exemplu, 
Python oferă o metodă append pentru clasa list care ne permite să adăugăm un element la 
sfârşitul listei. Prin urmare lista_mea.append('un item') va adăuga acel şir la 
lista_mea. De reţinut folosirea notaţiei cu punct pentru accesarea metodelor obiectelor. 
O clasă poate avea şi câmpuri (engl. fields) care nu sunt altceva decât variabile definite în raport 
exclusiv cu acea clasă. Se pot folosi acele variabile/nume numai în raport un obiect din acea clasă. 
Câmpurile sunt accesate tot prin notaţia cu punct, de exemplu lista.câmp. 
Exemplu: 
#!/usr/bin/python
# Fişier: using_list.py

# Lista mea de cumpărături


shoplist = ['mere', 'mango', 'morcovi', 'banane']

52
print('Am de cumpărat', len(shoplist), 'itemuri.')

print('Acestea sunt:', end=' ')


for item in shoplist:
print(item, end=' ')

print('\nTrebuie să cumpăr şi orez.')


shoplist.append('orez')
print('Lista mea de cumpărături este acum', shoplist)

print('Acum vom sorta lista')


shoplist.sort()
print('Lista sortată este', shoplist)

print('Primul lucru de cumpărat este', shoplist[0])


item_cumpărat = shoplist[0]
del shoplist[0]
print('Am cumpărat', item_cumpărat)
print('Lista mea este acum', shoplist)

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

Cum funcţionează: 
Variabila shoplist este o listă de cumpărături pentru cineva care merge la piaţă. În shoplist, 
memorăm şiruri care reprezintă numele lucrurilor pe care le avem de cumpărat, dar putem adăuga 
orice fel de obiect inclusiv numere sau alte liste. 
Am folosit bucla for..in pentru a itera prin itemurile listei. Până acum cred că aţi realizat ca o 
listă este şi secvenţă în acelaşi timp. Specificul secvenţelor va fi discutat întrun subcapitol următor. 
Observaţi utilizarea argumentului cuvânt cheie end al funcţiei print pentru a­i transmite că vrem 
să încheiem linia cu un spaţiu (' ') în loc de încheierea uzuală. 
În continuare adăugăm un item la listă folosind metoda append a obiectului listă, aşa cum am 
discutat anterior. Verificăm că adăugarea s­a realizat tipărind conţinutul listei prin transmiterea ei 
funcţiei print care o tipăreşte frumos pe ecran. 
Mai departe sortăm lista folosind metoda sort a listei. Este important să întelegem că această 
metodă afecteaza însăşi lista şi nu întoarce o listă modificată ­ spre deosebire de comportamentul 
sirurilor. Asta vrem să zicem prin muabile pe când şirurile sunt imuabile. 
După ce cumpărăm un item de la piaţă, vrem să­l eliminăm din listă. Pentru aceasta utilizăm 
declaraţia del. Trebuie menţionat aici itemul pe care vrem să­l eliminăm şi declaraţia del îl 

53
elimină pentru noi. Specificăm că vrem să eliminăm primul item, de aici declaraţia del
shoplist[0] (amintiţi­vă că Python începe numărătoarea de la 0). 
Dacă vreţi să ştiţi toate metodele definite de obiectul listă, citiţi help(list). 

Tupluri 
Tuplurile sunt folosite pentru păstra colecţii de obiecte. Sunt similare cu listele, dar fără 
funcţionalitatea 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 opţională de 
paranteze. 
Tuplurile sunt folosite de obicei în cazurile în care o declaraţie sau o funcţie definită de utilizator 
poate presupune fără risc de greşeală că o colecţie de valori nu se va schimba.. 
Exemplu: 
#!/usr/bin/python
# Fişier: using_tuple.py

zoo = ('piton', 'elefant', 'pinguin') # reţineţi că parantezele sunt opţionale


print('Numărul animalelor în zoo este', len(zoo))

zoo_nou = ('maimuţă', 'cămilă', zoo)


print('Numărul de cuşti î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('Numărul de animale în noul zoo este', len(zoo_nou)-1+len(zoo_nou[2]))

Rezultat: 
$ python using_tuple.py
Numărul animalelor în zoo este 3
Numărul de cuşti în noul zoo este 3
Animalele din noul zoo sunt ('maimuţă', 'cămilă', ('piton', 'elefant',
'pinguin'))
Animalele aduse din vechiul zoo sunt ('piton', 'elefant', 'pinguin')
Ultimul animal adus din vechiul zoo este pinguin
Numărul de animale în noul zoo este 5

Cum funcţionează: 
Variabila zoo este un tuplu de itemuri. Vedem că funcţia len lucrează şi pentru tupluri. De 
asemenea asta arată că tuplurile sunt şi secvenţe. 
Acum mutăm aceste animale într­un nou zoo, deoarece vechiul zoo s­a închis, să zicem. Ca urmare 
tuplul zoo_nou conţine nişte animale care erau acolo împreună cu animalele aduse din vechiul 
zoo. În realitate, acum, reţineţi că un tuplu în interiorul altui tuplu nu îşi pierde identitatea. 
Putem accesa itemurile din tuplu specificând poziţia întro pereche de paranteze pătrate, ca pentru 
liste. Acesta se numeşte operator de indexare. Accesăm al treilea item din zoo_nou specificând 
zoo_nou[2] şi accesăm al treilea item al tuplului zoo din tuplul zoo_nou specificând 
zoo_nou[2][2]. E destul de simplu după ce aţi înteles regula. 

54
Paranteze 
Deşi parantezele sunt opţionale, eu prefer să le pun mereu, pentru a face evident că e vorba de 
un tuplu, în special pentru a evita ambiguitatea. De exemplu print(1,2,3) şi 
print( (1,2,3) ) înseamnă două lucruri foarte diferite ­ prima tipăreşte trei numere, iar 
a doua tipăreşte un tuplu (care conţine trei numere). 

Tupluri cu 1 sau 0 elemente 
Un tuplu vid este construit folosind o pereche de paranteze goale myempty = (). Totuşi, un 
tuplu cu un singur element nu e aşa de simplu. Trebuie să îl specificaţi folosind virgula după 
primul (şi ultimul) element, ca Python să poată diferenţia între tuplu şi un alt obiect cuprins în 
paranteze întro expresie deci va trebui să specificaţi singleton = (2 , ) dacă vreţi să 
se înţeleagă 'tuplul care conţine 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 priveşte limbajul 
Python, ele sunt nişte obiecte stocate în alte obiecte. 

Dicţionare 
Un dicţionar este ca o carte de adrese în care poţi găsi 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 când nu poţi deosebi două persoane dacă au 
acelaşi nume. 
Pe post de chei puteţi 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 dicţionar folosind notaţia d = {cheie1 :
valoare1, cheie2 : valoare2 }. Observaţi că perechile cheie ­ valoare sunt separate 
prin virgulă, iar cheia este separată de valoare prin semnul două puncte. Dicţionarul este delimitat 
de o pereche de acolade. 
Reţineţi că întrun dicţionar perechile cheie ­ valoare nu sunt ordonate în nici un fel. Dacă vreţi o 
anumită ordine, va trebui să îl sortaţi singuri înainte de folosire. 
Dicţionarele pe care le veţi folosi sunt instanţe/obiecte ale clasei dict. 
Exemplu: 
#!/usr/bin/python
# Fişier: 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'])

55
# Ş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('Contactaţi pe {0} la adresa {1}'.format(nume, adresa))

# Adăugarea 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

Contactaţi pe Swaroop la adresa swaroop@swaroopch.com


Contactaţi pe Matsumoto la adresa matz@ruby-lang.org
Contactaţi pe Larry la adresa larry@wall.org

Adresa lui Guido este guido@python.org

Cum funcţionează: 
Creăm dicţionarul ab folosind notaţia deja discutată. Accesăm perechile cheie ­ valoare specificând 
cheia şi folosind operatorul de indexare, aşa cum am discutat la liste şi tupluri. Observaţi simplitatea 
sintaxei. 
Putem şterge perechi cheie valoare folosind vechiul nostru prieten ­ declaraţia del. Pur şi simplu 
specificăm dicţionarul şi operatorul de indexare pentru cheia care trebuie ştearsă şi le dăm 
declaraţiei del. Nu este necesar să se cunoască şi valoarea asociata cheii pentru a realiza această 
operaţie. 
În continuare accesăm fiecare pereche cheie ­ valoare din dicţionar folosind metoda items a 
dicţionarului care întoarce o listă de tupluri în care fiecare tuplu conţine o pereche de itemuri ­ cheia 
urmată de valoare. Extragem această pereche şi o atribuim variabilelor nume şi adresă
corespunzător pentru fiecare pereche folosind o buclă for..in în care tipărim aceste informaţii. 
Putem adăuga perechi noi cheie ­ valoare prin simpla utilizare a operatorului de indexare pentru a 
accesa cheia şi a atribui acea valoare, aşa cum am făcut pentru Guido în cazul de mai sus. 
Putem testa dacă există în dicţionar o anumită pereche cheie ­ valoare folosind operatorul in sau 
chiar metoda has_key a clasei dict. Puteţi consulta documentaţia pentru o listă completă a 
metodelor clasei dict folosind comanda help(dict). 
Argumente cuvânt cheie şi dicţionare 
Într­o altă ordine de idei, dacă aţi folosit argumente cuvânt cheie în funcţii, înseamnă că aţi 
folosit deja dicţionare! Ia gândiţi­vă: perechea cheie ­ valoare este specificată în lista de 
parametri a definiţiei funcţiei şi când accesaţi variabilele, numele lor sunt chei de acces ale 
unui dicţionar numit tabel de simboluri în terminologia proiectării de compilatoare). 

56
Secvenţe 
Listele, tuplurile şi şirurile sunt exemple de secvenţe, dar ce sunt secvenţele şi ce le face atât de 
speciale? 
Facilitatea cea mai importantă este că au teste de apartenenţă (adică expresiile in şi not in) şi 
operaţii de indexare. Operaţia de indexare ne permite să extragem direct un item din secvenţă. 
Au fost menţionate trei tipuri de secvenţe ­ liste, tupluri şi şiruri şi operaţia de feliere, care ne 
permite să extragem o parte (engl. slice) din secvenţă. 
Exemplu: 
#!/usr/bin/python
# Fişier: seq.py

shoplist = ['mere', 'mango', 'morcovi', 'banane']


nume = 'swaroop'

# Operaţia 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 sfârsit sunt', shoplist[2:])
print('Itemurile de la 1 la -1 sunt', shoplist[1:-1])
print('Itemurile de la început la sfârşit 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 sfârşit 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 sfârşit sunt ['morcovi', 'banane']
Itemurile de la 1 la -1 sunt ['mango', 'morcovi']
Itemurile de la început la sfârşit sunt ['mere', 'mango', 'morcovi',
'banane']
Caracterele de la 1 la 3 sunt wa
Caracterele de la 2 la sfârşit sunt aroop
Caracterele de la 1 la -1 sunt waroo
Caracterele de la început la sfârşit sunt swaroop

57
Cum funcţionează: 
La început, vedem cum se folosesc indecşii pentru a obţine un element anume din secvenţă. Asta se 
mai numeşte operaţia de subscriere. De câte ori specificaţi un număr întro pereche de paranteze 
drepte alăturate unei secvenţe, Python vă va extrage itemul corespunzator poziţiei în secvenţă. 
Reţineţi că Python începe numărătoarea de la 0. Astfel shoplist[0] extrage primul item şi 
shoplist[3] îl extrage pe al patrulea din secvenţa shoplist. 
Indexul poate fi şi un număr negativ, caz în care poziţia este calculată de la sfârşitul secvenţei. Din 
acest motiv shoplist[-1] indică ultimul item din secvenţă, iar shoplist[-2] penultimul 
item. 
Operaţia de feliere este folosită specificând numele secvenţei urmat de o pereche opţională de 
numere separate prin semnul doua puncte (engl. colon) incluse în paranteze drepte. Observaţi că 
este foarte asemănător cu operaţia de indexare folosită până acum. De reţinut că numerele sunt 
opţionale, semnul două puncte NU este opţional. 
Primul număr (înainte de două puncte) în operaţia de feliere indică punctul unde începe felia, iar al 
doilea număr indică unde se temină. Dacă nu este specificat primul număr, Python va începe cu 
începutul secvenţei. Dacă este omis al doilea număr, Python se va opri la sfârşitul secvenţei. 
Observaţi că felia întoarsă (uneori se spune 'returnată') începe cu poziţia dată de primul număr, dar 
se încheie imediat înainte de poziţia dată de al doilea număr adică începutul este inclus, sfârşitul nu 
este inclus în felie. 
Astfel, shoplist[1:3] întoarce o felie din secvenţa care începe cu poziţia 1, include poziţia 2, 
dar nu include poziţia 3 deci este întoarsă o felie de două itemuri. Similar, shoplist[:] întoarce 
o copie a secvenţei. 
Mai puteti face feliere şi cu indecşi negativi. Numerele negative sunt folosite pentru a indica poziţii 
de la sfârşitul secvenţei. De exemplu, shoplist[:-1] va întoarce o felie din secvenţă care 
exclude ultimul item din secvenţă, dar include tot restul secvenţei. 
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 întâmplă când pasul este 2, obţinem itemurile cu poziţiile 0, 2, ... Dacă pasul este 3, 
obtinem itemurile din poziţiile 0, 3, etc. 
Încercaţi variate combinaţii de specificaţii de feliere în modul interactiv, pentru a vedea imediat 
rezultatele. Marele avantaj al secvenţelor este că puteţi accesa tuplurile, listele şi şirurile în acelaşi 
fel! 

Seturi 
Seturile sunt colecţii neordonate de obiecte simple. Acestea sunt folosite atunci cand existenţa unui 

58
obiect în colecţie este mai importantă decât poziţia lui sau numărul de apariţii. 
Folosind seturi, puteţi testa apartenenţa, dacă un set este subset al altui set, puteţi afla intersecţia a 
două seturi şi aşa 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 funcţionează: 
Exemplul este autoexplicativ deoarece implică teoria de bază învăţată la şcoala despre mulţimi 
(seturi). 

Referinţe 
Când creaţi un obiect şi îi atribuiţi o valoare, variabila doar indică obiectul creat, nu reprezintă 
obiectul însuşi! Asta înseamnă că numele variabilei este un indicator către acea parte a memoriei 
calculatorului în care este stocat obiectul. Acest fapt se numeşte legare (engl. binding) a numelui la 
obiect. 
În general, nu trebuie să vă îngrijoraţi de asta, dar există un efect subtil darorat referinţei de care 
trebuie să fiţi conştienţi: 
Exemplu: 
#!/usr/bin/python
# Fişier: reference.py

print('Atribuire simplă')
lista_iniţială = ['mere', 'mango', 'morcovi', 'banane']
lista_mea = lista_iniţială # lista_mea este doar un alt nume al aceluiaşi
obiect!

del lista_iniţială[0] # Am cumpărat primul item, deci să-l ştergem din listă

print('lista initială este', lista_iniţială)


print('lista mea este', lista_mea)
# Observaţi că ambele liste apar fără 'mere', confirmând
# astfel că ele indică acelaşi obiect

print('Copiere făcând o felie intergală')


lista_mea = lista_iniţială[:] # Face o copie prin feliere integrală
del lista_mea[0] # eliminăm primul item

print('lista_iniţială este', lista_iniţială)


print('lista_mea este', lista_mea)
# Observaţi că acum cele două liste sunt diferite?

59
Rezultat: 
$ python reference.py
Atribuire simplă
lista_iniţială este ['mango', 'morcovi', 'banane']
lista_mea este ['mango', 'morcovi', 'banane']
Copiere făcând o felie intergală
lista_iniţială este ['mango', 'morcovi', 'banane']
lista_mea este ['morcovi', 'banane']

Cum funcţionează: 
Partea principală a explicaţiei se regăseşte în comentarii. 
Reţineţi că dacă vreţi să faceţi o copie a unei liste sau a unor obiecte complexe (nu simple obiecte, 
cum ar fi întregii), atunci trebuie să folosiţi felierea. Dacă folosiţi atribuirea obţineţi încă un nume 
pentru acelaşi obiect şi asta poate aduce probleme dacă nu sunteţi atenţi. 
Notă pentru programatorii în Perl 
Reţineţi că o declaraţie de atribuire pentru liste nu creeaza o copie. Va trebui să folosiţi 
felierea pentru a face o copie a secvenţei. 

Alte detalii despre şiruri 
Am discutat deja în detaliu despre şiruri. Ce ar mai putea fi de ştiut? Ei bine, ştiaţi că şirurile sunt 
obiecte şi au metode care fac orice de la verificarea unor părţi ale şirului până la eliminarea 
spaţiilor? 
Sirurile pe care le folosiţi în programe sunt obiecte din clasa str. Câteva metode utile sunt arătate 
în exemplul următor. Pentru o listă completă a metodelor, citiţi help(str). 
Exemplu: 
#!/usr/bin/python
# Fişier: 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 conţine subşirul "a"')

if name.find('war') != -1:
print('Da, şirul conţine subşirul "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 conţine subşirul "a"
Da, şirul conţine subşirul "war"

60
Brazilia_*_Rusia_*_India_*_China

Cum funcţionează: 
Aici vedem o mulţime de metode în acţiune. Metoda startswith este folosită pentru a testa dacă 
şirul începe sau nu cu un şir dat. Operatorul in se foloseşte pentru a verifica includerea unui şir în 
şirul dat. 
Metoda find este folosită pentru a găsi poziţia unui şir dat în şirul iniţial, care întoarce ­1 dacă nu 
a găsit nimic. Clasa str are şi o metodă simpatică join pentru a alătura 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 esenţiale pentru scrierea de programe de dimensiuni rezonabile. 
Acum că avem o mulţime de elemente Python asimilate, vom vedea cum se proiectează şi se scriu 
programe Python în lumea de zi cu zi. 

61
Python ro:Rezolvarea problemelor
Am explorat diverse părţi din limbajul Python şi acum vom vedea cum conlucrează acestea prin 
proiectarea şi scrierea unui program care face ceva util. Ideea este de a învăţa cum să scriem un 
program Python propriu. 

Problema 
Problema este "Vreau un program care să facă un backup al tuturor fişierelor mele importante". 
Deşi aceasta este o problema simplă, nu avem destule informaţii pentru a începe găsirea unei soluţii. 
Se impune o analiză suplimentară. De exemplu, cum specificăm care fişiere trebuie salvate? Cum 
vor fi ele stocate? Unde vor fi stocate? 
După o analiză corectă a problemei, proiectăm programul. Facem o listă cu lucruri care descriu cum 
trebuie să funcţioneze programul nostru. În acest caz, am creat lista următoare care descrie cum 
vreau EU să meargă. Dacă faceţi voi proiectarea s­ar putea să rezulte o altfel de analiză, întrucât 
fiecare face lucrurile în felul lui, deci e perfect OK. 
1. Fişierele şi directoarele care trebuie salvate sunt specificate într­o listă. 
2. Backup­ul trebuie stocat în directorul principal de backup 
3. Fişierele sunt stocate întro arhivă zip. 
4. Numele arhivei zip este data şi ora. 
5. Folosind comanda standard zip disponibilă implicit în toate distribuţiile Linux/Unix. 
Utilizatorii de Windows pot instala din pagina proiectului GnuWin32 şi adauga 
C:\Program Files\GnuWin32\bin la variabila de mediu PATH, similar modului în 
care am făcut pentru recunoaşterea însăşi a comenzii python. Reţineţi că puteţi folosi orice 
comandă de arhivare atât timp cât această are o interfaţă linie de comandă, ca să îi putem 
transmite argumente din programul nostru. 

Soluţia 
Întrucât designul programului nostru este relativ stabil, putem scrie codul care implementează 
soluţia noastră. 
#!/usr/bin/python
# Fişier: backup_ver1.py

import os
import time

# 1. Fişierele şi directoarele de salvat sunt specificate într-o listă.


source = ['"C:\\My Documents"', 'C:\\Code']
# Observaţi că a fost nevoie de ghilimele duble în interiorul şirului pentru a
proteja spaţiile din interiorul numelor.

# 2. Salvarea (engl. backup) trebuie stocată în directorul principal de backup


target_dir = 'E:\\Backup' # Nu uitaţi să schimbaţi asta cu directorul folosit de
voi

62
# 3. Fişierele 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 fişierele şi directoarele de salvat în


arhivă
zip_command = "zip -qr {0} {1}".format(target, ' '.join(source))

# Rulăm comanda de backup


if os.system(zip_command) == 0:
print('Salvare reuşită în ', target)
else:
print('Backup EŞUAT')

Rezultat: 
$ python backup_ver1.py
Salvare reuşită în E:\Backup\20090208153040.zip

Acum suntem în faza de testare în care verificăm 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, puneţi o declaraţie print(zip_command) imediat înainte de 
apelul os.system şi rulaţi programul. Acum copiaţi comanda zip_command la promptul shell­
ului şi verificaţi dacă merge pe cont propriu. Dacă aceasta eşuează, citiţi manualul comenzii zip ca 
să aflaţi ce ar putea fi greşit. Dacă reuşeşte, verificaţi programul Python ca să vedeţi dacă este exact 
ca mai sus. 
Cum funcţionează: 
Veţi observa cum am transformat designul în cod întro manieră pas cu pas. 
Utilizăm modulele os şi time importându­le de la început. Apoi specificăm directoarele care 
trebuie salvate în lista source. Directorul destinaţie este locul unde stocăm toate salvările şi acesta 
este specificat în variabila target_dir. Numele arhivei zip pe care o vom crea este "data 
curentă+ora curentă" pe care le găsim folosind funcţia time.strftime(). Arhiva va avea 
extensia .zip şi va fi stocată în directorul target_dir. 
Observaţi 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 
declaraţiei os.sep în locul acestor caractere va face programul mai portabil între aceste sisteme. 
Funcţia time.strftime() primeşte o specificaţie ca aceea folosită în program. Specificaţia %Y
va fi înlocuită cu anul, fără secol. Specificaţia %m va fi înlocuită cu luna, ca numar zecimal între 01
şi 12 ş.a.m.d. Lista completă a specificaţiilor poate fi găsită în Manualul de referinţă Python. 
Creăm numele directorului destinaţie folosind operatorul de adunare care concatenează şirurile 
adică alătură şirurile şi produce unul mai lung. Atunci noi creăm un şir zip_command care 
conţine comanda pe care o vom executa. Puteţi verifica dacă a rezultat o comandă corectă prin 
executarea ei de sine stătătoare într­un shell (terminal Linux sau DOS prompt). 
Comanda zip pe care o folosim are câteva opţiuni şi parametri transmişi. Opţiunea -q este folosită 
pentru a indica modul de lucru tăcut (engl. quiet). Opţiunea -r specifică modul recursiv de 
parcurgere a directoarelor, adică trebuie să includă şi toate subdirectoarele şi subdirectoarele 
acestora etc. Cele două opţiuni se combină şi se specifică pe scurt -qr. Opţiunile sunt urmate de 

63
numele arhivei care va fi creată urmată de lista fişierelor şi directoarelor de salvat. Convertim lista 
source într­un şir folosind metoda join a şirurilor, pe care am învăţat deja s­o folosim. 
În fine, rulăm comanda folosind funcţia 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 funcţie de rezultatul comenzii, tipărim pe ecran mesajul adecvat, cum că salvarea a reuşit sau nu. 
Asta e, am creat un script care să faca un backup al fişierelor importante din sistem! 
Notă pentru utilizatorii de Windows 
În locul secvenţelor de evadare cu dublu backslash, puteţi folosi şi şiruri brute. De exemplu, 
folosiţi 'C:\\Documents' sau r'C:\Documents'. În orice caz, nu folosiţi 
'C:\Documents' întrucât veţi ajunge să folosiţi o secvenţă de evadare necunoscută, \D. 

Acum că avem un script funcţional de salvare, îl putem rula de câte ori vrem să obţinem o salvare a 
fişierelor. Utilizatorii de Linux/Unix sunt sfătuiţi să folosească metode executabile aşa cum am 
discutat în capitolele precedente, astfel ca ele să poată rula de oriunde, oricând. Asta se numeşte 
faza de operare sau de distribuire a software­ului. 
Programul de mai sus funcţionează corect, dar (de obicei) primul program nu funcţionează cum ne­
am aştepta. 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ă veţi întoarce la 
faza de design sau debuggigg pentru a rezolva problema. 

A doua versiune 
Prima versiune a scriptului nostru funcţionează. Totuşi, putem rafina programul pentru a lucra mai 
bine în utilizarea sa de zi cu zi. Asta se numeşte întreţinere 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 
salvărilor, folosind ora ca nume al fişierului, iar data ca nume de subdirector al directorului de 
backup care să conţină salvările din aceeaşi data. Primul avantaj este că salvările vor fi stocate într­o 
manieră ierarhică şi vor fi mai uşor de gestionat. Al doilea avantaj este că lungimea numelor de 
fişier va fi mai mult mai mică. Al treilea avantaj este că se va putea verifica mai uşor dacă au fost 
făcute salvări zilnic (în ziua în care nu s­a facut, directorul având ca nume acea dată lipseşte, 
întrucât nu a fost creat). 
#!/usr/bin/python
# Fişier: backup_ver2.py

import os
import time

# 1. Fişierele şi directoarele de salvat sunt specificate întro listă.


source = ['"C:\\My Documents"', 'C:\\Code']
# Observaţi că au fost necesare ghilimele duble pentru a proteja spaţiile din
interiorul numelor.

# 2. Salvarea trebuie stocată în directorul principal de backup


target_dir = 'E:\\Backup' # Nu uitaţi să schimbaţi asta cu directorul pe care îl
folosiţi voi

64
# 3. Fişierele sunt salvate în fişiere 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')

# Creăm subdirectorul, dacă nu exista înainte


if not os.path.exists(azi):
os.mkdir(azi) # creăm directorul
print('Am creat cu succes directorul ', azi)

# Numele fişierului arhiva zip


target = azi + os.sep + acum + '.zip'

# 5. Folosim comanda zip pentru a colecta fişierele în arhivă.


zip_command = "zip -qr {0} {1}".format(target, ' '.join(source))

# Rulăm programul de salvare


if os.system(zip_command) == 0:
print('Salvare reuşită în ', target)
else:
print('Salvare EŞUATĂ')

Rezultat: 
$ python backup_ver2.py
Am creat cu succes directorul E:\Backup\20090209
Salvare reuşită în E:\Backup\20090209\111423.zip

$ python backup_ver2.py
Salvare reuşită în E:\Backup\20090209\111837.zip

Cum funcţionează: 
Majoritatea codului ramâne neschimbat. Schimbările constau un testarea existenţei directorului 
având ca nume data curentă în interiorului directorului principal de backup folosind funcţia 
os.path.exists. Dacă acesta nu există, îl creăm noi folosind funcţia os.mkdir. 

Versiunea a treia 
A doua versiune merge bine când facem multe salvări, dar e greu de văzut ce este salvat în fiecare 
arhiva! De exemplu, poate am făcut o schimbare mare unui program sau unei prezentări şi aş vrea să 
asociez aceste schimbări cu numele programului sau prezentării şi arhiva zip. Aceasta se poate 
realiza uşor prin ataşarea unui comentariu furnizat de utilizator la numele arhivei zip. 
Notă 
Următorul program nu funcţionează, deci nu va alarmaţi, urmaţi­l totuşi, pentru că e o lecţie 
în el. 

#!/usr/bin/python
# Fişier: backup_ver3.py

import os
import time

65
# 1. Fişierele şi directoarele de salvat sunt specificate întro listă.
source = ['"C:\\My Documents"', 'C:\\Code']
# Observaţi că a fost nevoie de ghilimele duble pentru a proteja spaţiile din
interiorul numelor.

# 2. Salvarea trebuie stocată în directorul principal


target_dir = 'E:\\Backup' # Nu uitaţi să schimbaţi asta cu ce folosiţi voi
# 3. Fişierele 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')

# Luăm un comentariu de la utilizator pentru a crea numele


comentariu = input('Introduceţi un comentariu --> ')
if len(comentariu) == 0: # Verificaţi dacă a fost introdus
target = azi + os.sep + acum+ '_' +
comentariu.replace(' ', '_') + '.zip'

# Creăm subdirectorul dacă nu există deja


if not os.path.exists(azi):
os.mkdir(azi) # Creăm directorul
print('Am creat cu succes directorul ', azi)

# 5. Folosim comanda zip pentru a colecta fişierele în arhiva


zip_command = "zip -qr {0} {1}".format(target, ' '.join(source))

# Rulăm salvarea
if os.system(zip_command) == 0:
print('Salvare reuşită în ', target)
else:
print('Salvare EŞUATĂ')

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

Cum (nu) funcţionează: 
Acest program nu funcţionează! 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 aşteaptă Python să o găsească 
acolo. Când vedem eroarea dată de Python, aflăm şi locul unde a detectat el eroarea. Deci începem 
eliminarea erorilor (engl. debugging) programului de la acea linie. 
La o observaţie atentă, vedem ca o linie logică a fost extinsă pe două linii fizice fără să se specifice 
acest lucru. În esenţă Python a găsit operatorul de adunare (+) fără vreun operand în acea linie şi 
prin urmare nu ştie cum să continue. Vă amintiţi că putem specifica trecerea unei linii logice pe 
următoarea linie fizică folosind un backslash la sfârşitul liniei fizice. Astfel facem corectura la 
progrmul nostru. Aceasta corecţie a programului când gasim erori se numeşte depanare (engl. bug 
fixing). 

66
Versiunea a patra 
#!/usr/bin/python
# Fişier: backup_ver4.py

import os
import time

# 1. Fişierele de salvat sunt specificate întro listă.


source = ['"C:\\My Documents"', 'C:\\Code']
# Observaţi că a trebuit să punem ghilimele duble pentru a proteja spaţiile din
interiorul numelor.

# 2. Salvarea trebuie stocată în directorul principal de backup


target_dir = 'E:\\Backup' # Nu uiţati să schimbaţi asta cu ceea ce folosiţi voi

# 3. Salvările 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')

# Acceptăm un comentariu de la utilizator


comentariu = input('Introduceţi un comentariu --> ')
if len(comentariu) == 0: # Verificăm dacă a fost introdus un comentariu
target = azi + os.sep + acum + '.zip'
else:
target = azi + os.sep + acum + '_' + \
comentariu.replace(' ', '_') + '.zip'

# Creăm subdirectorul, dacă nu exista deja


if not os.path.exists(azi):
os.mkdir(azi) # creăm directorul
print('Am creat cu succes directorul ', today)

# 5. Folosim comanda zip pentru a colecta fişierele în arhivă zip


zip_command = "zip -qr {0} {1}".format(target, ' '.join(source))

# Rulăm comanda de backup


if os.system(zip_command) == 0:
print('Salvare reuşită în ', target)
else:
print('Salvare EŞUATĂ')

Rezultat: 

$ python backup_ver4.py
Introduceţi un comentariu --> noi exemple adăugate
Salvare reuşită în E:\Backup\20090209\162836_noi_exemple_adăugate.zip

$ python backup_ver4.py
Introduceţi un comentariu -->
Salvare reuşită în E:\Backup\20090209\162916.zip

Cum functionează: 

67
Acest program funcţionează, acum! Să parcurgem îmbunătăţirile pe care i le­am adus în versiunea 3. 
Acceptăm un comentariu de la utilizator folosind funcţia input şi apoi testăm dacă s­a introdus 
ceva sau nu calculând lungimea şirului introdus cu ajutorul funcţiei len. Dacă utilizatorul a dat 
ENTER fără să introducă ceva (poate era doar un backup de rutină şi n­au fost făcute modificări 
anume), apoi continuăm ca mai înainte. 
Totuşi, dacă a fost introdus un comentariu, acesta este ataşat numelui arhivei zip, chiar înaintea 
extensiei .zip. Observaţi că înlocuim spaţiile în comentariu cu underscore ­ ca să fie mai uşoară 
gestiunea fişierelor cu nume lungi. 

Alte rafinamente 
A patra versiune este una satisfăcătoare 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 opţiunii -v Pentru a face programul mai vorbăreţ. 
Altă îmbunătăţire posibilă ar fi să permitem ca fişierele şi directoarele de salvat să fie transmise 
scriptului la linia de comandă. Noi le putem culege din lista sys.argv şi le putem adăuga la 
variabila listă source folosind metoda extend a clasei list. 
Cea mai importanta extindere ar fi să nu folosim os.system ci direct modulele predefinite 
zipfile sau tarfile pentru a crea aceste arhive. Ele sunt parte a bibliotecii standard şi sunt 
deja disponibile pentru a scrie un program fără dependente externe pentru programul de arhivare. 
Totuşi, am folosit os.system pentru crearea salvărilor din motive pedagogice, pentru ca exemplul 
să fie destul de simplu de înteles, dar şi util. 
Puteţi încerca să scrieţi a cincea variantă folosind modulul zipfile în locul apelului os.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 testăm şi o 
depanăm. O folosim pentru a ne asigura că merge cum ne­am propus. Acum îi adăugăm noi facilităţi 
pe care le dorim şi parcurgem ciclul FACI ­ TESTEZI ­ UTILIZEZI de câte ori este nevoie. Reţineţi, 
Software­ul este crescut, nu construit. 

Rezumat 
Am văzut cum se creează un program/script Python şi diferite stadii implicate de scrierea unui 
program. Aţi putea considera utilă scrierea de programe proprii, atât pentru acomodarea cu Python 
cât şi pentru a rezolva probleme. 

68
În continuare vom discuta despre programarea orientată pe obiecte. 

69
Python ro:Programare orientată pe obiecte

Introducere 
În toate programele folosite până acum ne­am construit soluţiile în jurul funcţiilor adică blocuri de 
declaraţii care manipulează date. Acest mod de programare se numeşte orientat pe proceduri. Există 
şi un alt mod de organizare a programelor, în care funcţionalitatea şi datele sunt împachetate 
împreună în unităţi numite obiecte. Acest mod de structurare defineşte paradigma "orientat pe 
obiecte. Aproape tot timpul puteţi folosi abordări procedurale în programare, dar când scrieţi 
programe mari sau aveţi de rezolvat probleme care sunt mai aproape de acest mod de structurare,  
puteţi folosi tehnicile de programare orientată pe obiecte.. 
Clasele şi obiectele sunt două aspecte ale programării orientate pe obiecte. O clasă creeaza un nou 
tip în care obiectele sunt instanţe ale clasei. O analogie este că puteţi avea variabile de tip int care 
se traduce prin aceea că variabilele care stochează întregi sunt instanţe (obiecte) ale clasei int. 
Notă pentru programatorii în limbaje cu tipuri statice 
Observaţi că până şi întregii sunt trataţi 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 găsi o similaritate cu conceptele de încapsulare şi 
decapsulare. 

Obiectele pot stoca date folosind variabile obişnuite care aparţin obiectului. Variabilele care aparţin 
unui obiect sunt numite câmpuri. Obiectele pot avea şi funcţionalitate folosind funcţii care aparţin 
clasei. Aceste funcţii se munesc metode ale clasei. Această terminologie este importantă deoarece 
ne ajuta să diferenţiem între funcţii şi variabile independente şi cele aparţinând unui obiect sau unei 
clase. Împreună, variabilele şi funcţiile care aparţin unei clase se numesc atribute ale clasei. 
Câmpurile sunt de două tipuri ­ ele pot aparţine fiecărei instanţe/obiect al clasei sau pot aparţine 
însăşi clasei. Acestea sunt numite variabile de instanţă respectiv variabile ale clasei. 
O clasă este creată folosind cuvântul cheie class. Câmpurile şi metodele clasei sunt listate întrun 
bloc indentat. 

self 
Clasele şi metodele au o diferenţă specifică faţă de funcţiile obişnuite ­ ele trebuie să aibă un 
prenume suplimentar care trebuie adăugat la începutul listei de parametri, dar nu trebuie să­i daţi o 
valoare când apelaţi metoda, Python o va furniza. Această variabilă specială se referă la obiectul 
însuşi (engl. self) şi prin convenţie este numită self. 
Cu toate acestea, deşi puteţi să­i daţi orice nume acestui parametru, este puternic recomandat să 
folosiţi numele self ­ orice alt nume este dezaprobat. Există multe avantaje în folosire numelui 
standard ­ orice cititor al programului va înţelege imediat despre ce este vorba şi chiar mediile IDE 
(Integrated Development Environments) specializate te pot ajuta dacă foloseşti self. 

70
Notă pentru programatorii în C++/Java/C# 
self din Python este echivalent cu pointerul this din C++ şi cu referinţa this din Java şi 
C#. 

Probabil vă întrebaţi cum dă Python valoarea corectă lui self şi de ce nu trebuie să­i dăm o 
valoare. Un exemplu va clarifica această problemă. Să zicem că aveţi o clasă numită MyClass şi o 
instanţă a acestei clase, numită myobject. Când apelaţi o metodă a acestui obiect 
myobject.method(arg1, arg2), apelul este automat convertit de Python în 
MyClass.method(myobject, arg1, arg2) ­ asta e toată marea specialitate a lui self. 
Asta înseamnă şi că dacă aveţi o metodă care nu primeşte argumente, tot va trebui să aveţi un 
argument ­ self. 

Clase 
Cea mai simplă clasă posibilă este arătată în exemplul următor. 
#!/usr/bin/python
# Fişier: simplestclass.py

class Persoana:
pass # Un bloc gol

p = Persoana()
print(p)

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

Cum funcţionează: 
Creăm o clasă nouă folosind declaraţia class şi numele clasei. Aceasta este urmată de un bloc 
indentat de declaraţii care formează corpul clasei. În acest caz avem un bloc gol, arătat de declaraţia 
pass. 
În continuare creăm un obiect/instanţă a acestei clase folosind numele clasei urmat de o pereche de 
paranteze. (Vom învăţa mai multe despre instanţiere în paragraful următor). Pentru propria 
verificare, confirmăm tipul variabilei prin simpla ei tipărire. Aflăm că avem o instanţă a variabilei 
din clasa Persoana din modulul __main__. 
Observaţi că a fost tipărită ş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 funcţiile, doar că au un argument 
self în plus. Iată un exemplu. 
#!/usr/bin/python
# Fişier: metoda.py

class Persoana:

71
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 funcţionează: 
Aici vedem particula self în acţiune. Observaţi că metoda ziSalut nu primeşte parametri, dar 
tot are argumentul self în definiţia funcţiei. 

Metoda __init__ 
Există multe nume de metode care au un înteles special în clasele Python. Acum vom afla 
semnificaţia metodei __init__. 
Metoda __init__ este executată imediat ce este instanţiat un obiect al clasei. Metoda este utilă 
pentru a face iniţializarea dorită pentru obiectul respectiv. Observaţi că numele este încadrat cu 
dublu underscore. 
Exemplu: 
#!/usr/bin/python
# Fişier: 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 funcţionează: 
Definim metoda __init__ să ia un parametru nume (pe lângă obişnuitul self). În acest caz 
creăm doar un câmp numit nume. Observaţi că deşi ambele sunt numite 'nume', cele două sunt 
obiecte diferite. Notaţia cu punct ne permite să le deosebim. 
Cel mai important, observaţi că nu apelăm explicit metoda __init__ ci îi transmitem argumentele 
în paranteză după numele clasei în momentul creării obiectului/instanţa a clasei. Aceasta este 
semnificaţia acestei metode. 

72
Acum putem să folosim câmpul self.name în metodele noastre, ceea ce este arătat în metoda 
ziSalut. 

Variabile de clasă, variabile de instanţă 
Am discutat deja partea de funcţionalitate a claselor şi obiectelor (adică metodele), acum să învăţăm 
ceva despre partea de date. Partea de date, aşa­numitele câmpuri, nu sunt altceva decât variabile 
obişnuite care sunt legate de spaţiile 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 spaţii de nume (engl. name spaces). 
Există două feluri de câmpuri ­ variabile de clasa şi variabile de obiect/instanţă, care sunt clasificate 
în funcţie de proprietarul variabilei. 
Variabilele de clasă sunt partajate ­ ele pot fi accesate de toate instanţele acelei clase. Există doar un 
exemplar al variabilei de clasă şi când o instanţă îi modifică valoarea, această modificare este văzută 
imediat de celelalte instanţe. 
Variabilele de instanţă sunt proprietatea fiecărei instanţe a clasei. În acest caz, fiecare obiect are 
propriul exemplar al acelui câmp adică ele nu sunt relaţionate în nici un fel cu câmpurile având 
acelaşi nume în alte insţante. Un exemplu va ajuta la înţelegerea situaţiei: 
#!/usr/bin/python
# Fişier: objvar.py

clasa Robot:
'''Reprezintă un robot cu nume.'''

# O variabilă de clasă, numărătorul populaţiei de roboţi


populaţie = 0

def __init__(self, nume):


'''Iniţializează datele.'''
self.nume = nume
print('(Iniţializez robotul {0})'.format(self.nume))

# Când această instanţă este creată, robotul se


# adaugă la populaţie
Robot.populaţie += 1

def __del__(self):
'''Dispar...'''
print('{0} este dezmembrat!'.format(self.nume))

Robot.populaţie -= 1

if Robot.populaţie == 0:
print('{0} a fost ultimul.'.format(self.nume))
else:
print('Mai există {0:d} roboţi apţi de
lucru.'.format(Robot.populaţie))

def ziSalut(self):
'''Salutare de la robot.

Da, pot să facă şi asta.'''


print('Salut. Stăpânii mei îmi zic {0}.'.format(self.nume))

73
def câţi():
'''Tipăreşte populaţia curentă.'''
print('Avem {0:d} roboţi.'.format(Robot.populaţie))
câţi = staticmethod(câţi)

droid1 = Robot('R2-D2')
droid1.ziSalut()
Robot.câţi()

droid2 = Robot('C-3PO')
droid2.ziSalut()
Robot.câţi()

print("\nRoboţii pot să facă nişte treabă aici.\n")

print("Roboţii au terminat treaba. Deci să-i distrugem.")


del droid1
del droid2

Robot.câţi()

Rezultat: 
(Iniţializez robotul R2-D2)
Salut. Stăpânii mei îmi zic R2-D2.
Avem 1 roboţi.
(Iniţializez robotul C-3PO)
Salut. Stăpânii mei îmi zic C-3PO.
Avem 2 roboţi.

Roboţii pot să facă nişte treabă aici.

Roboţii au terminat treaba. Deci să-i distrugem.


R2-D2 este dezmembrat!
Mai există 1 roboţi apţi de lucru.
C-3PO este dezmembrat!
C-3PO a fost ultimul.
Avem 0 roboţi.

Cum funcţionează: 
Este un exemplu lung, dar ajută la evidenţierea naturii variabilelor de clasă şi de instanţă. Aici 
câmpul populaţie aparţine clasei Robot şi este deci o variabilă de clasă. Variabila nume
aparţine obiectului (îi este atribuită folosind self.) deci este o variabilă de obiect/instanţă. 
Asadar ne referim la variabila de clasă populaţie cu notaţia Robot.populaţie şi nu cu 
self.populaţie. Ne referim la variabila de instanţă nume cu notaţia self.nume în metodele 
acelui obiect. Amintiţi­vă această diferenţă simplă între variabilele de clasă şi de instanţă. Mai 
observaţi şi că o variabilă de obiect cu acelaşi nume ca o variabilă de clasă, va ascunde variabila de 
clasă faţă de metodele clasei! 
Metoda câţi este în fapt o metodă a clasei şi nu a instanţei. Asta înseamnă că trebuie să o definim 
cu declaraţia classmethod sau staticmethod Dacă vrem să ştim cărui spaţiu de nume îi 
aparţine. Întrucât nu vrem aceasta informaţie, o vom defini cu staticmethod. 
Am fi putut obţine acelaşi lucru folosind decoratori: 
@staticmethod

74
def câţi():
'''Tipăreşte populaţia curentă.'''
print('Avem {0:d} roboti.'.format(Robot.populaţie))

Decoratorii pot fi concepuţi ca scurtături pentru apelarea unor declaraţii explicite, aşa cum am văzut 
în acest exemplu. 
Observaţi că metoda __init__ este folosită pentru a iniţializa cu un nume instanţa clasei Robot. 
În această metodă, mărim populaţie cu 1 intrucât a fost creat încă un robot. Mai observaţi şi că 
valoarea self.nume este specifică fiecărui obiect, ceea ce indică natura de variabilă de instanţă a 
variabilei. 
Reţineţi că trebuie să vă referiţi la variabilele şi metodele aceluiaşi obiect numai cu self. Acest 
mod de indicare se numeşte referinţă la atribut. 
În acest program mai vedem şi docstrings pentru clase şi metode. Putem accesa docstringul clasei 
în runtime (rom. timpul execuţiei) folosind notaţia Robot.__doc__ şi docstring­ul metodei 
ziSalut cu notaţia Robot.ziSalut.__doc__ 
Exact ca şi metoda __init__, mai există o metodă specială, __del__, care este apelată atunci 
când un obiect trebuie distrus, adică nu va mai fi folosit, iar resursele lui sunt returnate sistemului. 
În această metodă reducem şi numărul Robot.populaţie cu 1. 
Metoda __del__ este executată dacă obiectul nu mai este în folosinţă şi nu există o garanţie că 
metoda va mai fi rulată. Dacă vreţi să o vedeţi explicit în acţiune, va trebui să folosiţi declaraţia del
cum am făcut noi aici. 
Notă pentru programatorii în C++/Java/C# 
Toţi membrii unei clase (inclusiv membrii date) sunt publici şi toate metodele sunt virtual în 
Python. 
O excepţie: Dacă folosiţi membrii date cu nume care încep cu dublu underscore precum 
__var_privată, Python exploatează acest aspect şi chiar va face variabila să fie privată. 
Aşadar, convenţia 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/instanţe. Reţineţi că aceasta este doar o convenţie şi nu 
este impusă de Python (exceptând prefixul dublu underscore). 

Moştenire 
Un beneficiu major al programării orientate pe obiecte este refolosirea codului şi o cale de a obţine 
asta este mecanismul de moştenire. Moştenirea poate fi descrisă cel mai bine ca şi cum ar 
implementa o relaţie între un tip şi un subtip între clase. 
Să zicem că scrieţi un program în care trebuie să ţineţi evidenţa profesorilor şi studenţilor într­un 
colegiu. Ei au unele caracteristici comune, precum nume, adresă, vârstă. Ei au şi caracteristici 
specifice, cum ar fi salariul, cursurile şi perioadele de absenţă, pentru profesori, respectiv notele şi 
taxele pentru studenţi. 
Puteţi crea două clase independente pentru fiecare tip şi procesa aceste clase prin adăugarea de 
caracteristici noi. Aşa programul devine repede un hăţis necontrolabil. 
O cale mai bună ar fi să creaţi o clasă comună numită MembruAlŞcolii şi să faceţi clasele 
student şi profesor să moştenească de la această clasă, devenind astfel subclase ale acesteia, şi apoi 

75
să adăugaţi caracteristici la aceste subtipuri. 
Această abordare are multe avantaje. Dacă facem vreo schimbare la funcţionalitatea clasei 
MembruAlŞcolii, ea este automat reflectată şi în subtipuri. De exemplu, puteţi adăuga un nou 
câmp card ID şi pentru studenţi şi pentru profesori prin simpla adăugare a acestuia la clasa 
MembruAlŞcolii. Totuşi, schimbările din subtipuri nu afectează alte subtipuri. Alt avantaj este că 
puteţi face referire la un profesor sau student ca obiect MembruAlŞcolii object, ceea ce poate fi 
util în anumite situaţii precum calculul numărului de membri ai şcolii. Acest comportament este 
numit polimorfism, în care un subtip poate fi folosit în orice situatie în care se aşteaptă folosirea 
unui tip părinte adică obiectul poate fi tratat drept instanţă a tipului părinte. 
Observaţi şi că refolosim codul clasei părinte şi nu e nevoie să­l repetăm în subclase cum am fi fost 
nevoiţi dacă am fi creat clase independente. 
Clasa MembruAlŞcolii în această situaţie este numită clasa bază sau superclasa. Clasele 
profesor şi student sunt numite clase derivate sau subclase. 
Vom vedea acest exemplu pe un program. 
#!/usr/bin/python
# Fişier: inherit.py

class MembruAlŞcolii:
'''Reprezintă orice membru al şcolii.'''
def __init__(self, nume, vârstă):
self.nume = nume
self.varsta = vârstă
print('(Iniţializez MembruAlŞcolii: {0})'.format(self.nume))

def descrie(self):
'''Afişează detaliile mele.'''
print('Nume:"{0}" Vârstă:"{1}"'.format(self.nume, self.vârstă), end=" ")

class profesor(MembruAlŞcolii):
'''Reprezintă un profesor.'''
def __init__(self, nume, vârstă, salariu):
MembruAlŞcolii.__init__(self, nume, vârstă)
self.salariu = salariu
print('(Iniţializez Profesor: {0})'.format(self.nume))

def descrie(self):
MembruAlŞcolii.descrie(self)
print('Salariu: "{0:d}"'.format(self.salariu))

class student(MembruAlŞcolii):
'''Reprezintă un student.'''
def __init__(self, nume, vârstă, note):
MembruAlŞcolii.__init__(self, nume, vârstă)
self.note = note
print('(Iniţializez student: {0})'.format(self.nume))

def descrie(self):
MembruAlŞcolii.descrie(self)
print('Note: "{0:d}"'.format(self.note))

p = profesor('D-na. Shrividya', 40, 30000)


s = student('Swaroop', 25, 75)

print() # Afişează o linie goală

76
membri = [p, s]
for membru in membri:
membru.descrie() # Funcţionează şi pentru profesor şi pentru student

Rezultat: 
$ python inherit.py
(Iniţializez MembruAlŞcolii: Mrs. Shrividya)
(Iniţializez profesor: D-na. Shrividya)
(Iniţializez MembruAlŞcolii: Swaroop)
(Iniţializez student: Swaroop)

Nume:"D-na. Shrividya" Vârstă:"40" Salariu: "30000"


Nume:"Swaroop" Vârstă:"25" Note: "75"

Cum funcţionează: 
Pentru a folosi moştenirea, specificăm clasele bază întrun tuplu care urmează numele în definiţia 
clasei. Apoi observăm că metoda __init__ a clasei bază este apelată explicit folosind variabila 
self ca să putem iniţializa partea din obiect care provine din clasa bază. Este foarte important de 
reţinut ­ Python nu apeleaza automat constructorul clasei bază, trebuie să faceţi asta explicit. 
Mai observăm că apelurile către clasa bază se fac prefixind numele clasei apelului metodelor şi 
punând variabila self împreună cu celelalte argumente. 
Se confirmă că folosim instanţele claselor profesor şi student ca şi cum ar fi instanţe ale 
clasei MembruAlŞcolii când folosim metoda descrie a clasei MembruAlŞcolii. 
În plus, observaţi că este apelată metoda descrie a subtipului nu metoda descrie a clasei 
MembruAlŞcolii. O cale de a întelege asta este că Python începe întotdeauna căutarea 
metodelor în tipul curent, ceea ce face în acest caz. Dacă nu ar fi găsit metoda, ar fi căutat în clasele 
părinte, una câte una, în ordinea specificată în tuplul din definiţia clasei. 
O notă asupra terminologiei ­ daca în tuplul de moştenire este listată mai mult de o clasă, acest caz 
este de moştenire multiplă. 

Rezumat 
Am explorat diverse aspecte ale claselor şi obiectelor precum şi diferite terminologii asociate cu 
acestea. Am văzut de asemenea beneficiile şi punctele slabe ale programării orientate pe obiecte. 
Python este puternic orientat pe obiecte şi înţelegerea acestor concepte vă va ajuta enorm în cariera 
de programator. 
Mai departe vom învăţa să tratăm cu intrările şi ieşirile şi cum să accesam fişiere în Python. 

77
Python ro:Intrări/ieşiri

Introducere 
Există situaţii în care programul la care lucraţi trebuie să interacţioneze cu utilizatorul. De exemplu, 
vreţi să preluaţi date de la utilizator şi să tipăriţi nişte rezultate. Putem folosi funcţiile input() şi 
print(). 
Pentru ieşire, putem folosi şi diverse metode ale clasei str (string). De exemplu, putem folosi 
metoda rjust pentru a alinia judicios la dreapta pe o anumită lungime. A se vedea help(str)
pentru detalii suplimentare. 
Alt tip obişnuit de intrare/ieşire este lucrul cu fişiere. Capacitatea de a crea, citi şi scrie fişiere este 
esenţială pentru programele pe care le vom scrie în acest capitol. 

Intrări de la utilizator 
#!/usr/bin/python
# FIşier: user_input.py

def reverse(text):
return text[::-1]

def is_palindrome(text):
return text == reverse(text)

ceva = input('Introduceţi textul: ')


if (is_palindrome(ceva)):
print("Da, este un palindrom")
else:
print("Nu, nu este un palindrom")

Rezultat: 
$ python user_input.py
Introduceţi textul: şir
Nu, nu este un palindrom

$ python user_input.py
Introduceţi textul: madam
Da, este un palindrom

$ python user_input.py
Introduceţi textul: racecar
Da, este un palindrom

Cum funcţionează: 
Folosim facilitatea de feliere pentru a inversa textul. Am învăţat deja cum să facem felii din secvenţe 
între poziţiile a şi b folosind formula seq[a:b]. Putem da şi un al treilea argument care 
determină pasul felierii. Pasul implicit este 1 motiv pentru care va rezulta o porţiune continuă din 

78
text. Cu un pas negativ, de exemplu -1 textul va fi inversat. 
Funcţia input() ia ca argument un şir şi îl afişează utilizatorului. Apoi asteaptă utilizatorul să 
introducă ceva şi să apese tasta ENTER. În acel moment funcţia input() va întoarce în program 
textul introdus. 
Luăm acel text şi îl inversăm. Dacă originalul şi textul inversat sunt identice, textul este un 
palindrom (definiţia pentru limba engleza). 
Tema pentru acasă: 
Verificarea calităţii de palindrom ar trebui să ignore punctuaţia, spaţiile şi cazul caracterelor. De 
exemplu "Ele fac cafele." este de asemenea palindrom, dar programul nostru spune că nu. Puteţi 
îmbunătăţi acest program ca să recunoască acest palindrom? 

Fişiere 
Puteţi deschide fişiere pentru scriere sau citire prin crearea unui obiect din clasa file (rom. fişier) 
şi folosind metodele sale read, readline sau write după caz. Capacitatea de a citi sau scrie 
întrun fişier depinde de modul în care aţi specificat fişierul în declaraţia de deschidere. În final, 
când aţi terminat lucrul cu fişierul, puteţi apela metoda close pentru a­i da lui Python să­l închidă. 
Exemplu: 
#!/usr/bin/python
# Fişier: using_file.py
from __future__ import print_function

poem = '''\
Programming is fun
When the work is done
if you wanna make your work also fun:
use Python!
'''

f = open('poem.txt', 'w') # Deschidere pentru scriere


# 'w' vine de la 'writing' (rom. scriere)
f.write(poem) # scriem textul în fişier
f.close() # închidem fişierul
f = open('poem.txt') # Dacă nu este specificat modul, se presupune citire, 'r'
vine de la 'read' (rom. citire)
while True:
linie = f.readline()
if len(linie) == 0: # Lungime 0 indică EOF - sfârşitul fişierului (engl. End
Of File)
break
print(linie, end='')
f.close() # închidem fişierul

Rezultat: 
$ python using_file.py
Programming is fun
When the work is done
if you wanna make your work also fun:
use Python!

79
Cum funcţionează: 
Întâi deschidem un fişier folosind funcţia predefinită open şi specificând numele fişierului şi 
modul în care vrem să fie deschis fişierul. Modul poate fi 'mod citire' ('r'), mod 'scriere' ('w') 
sau mod 'adăugare la sfârşit' ('a') (engl. append). Putem folosi şi ('t') pentru fişiere text sau 
('b') pentru fişiere binare. În realitate există multe moduri posibile, pe care le puteţi afla lansând 
help(open). Implicit, open() consideră fişierul 't'ext şi îl deschide în mod 'r' (citire). 
În exemplul nostru deschidem fişierul în mod scriere şi folosim metoda write a obiectului fişier 
pentru a scrie în fişier şi apoi îl închidem cu funcţia close. 
În continuare deschidem acelaşi fişier din nou, în mod citire. Nu avem nevoie să specificăm modul 
deoarece este cel implicit. Citim fiecare linie folosind funcţia readline întro buclă. Această 
metoda întoarce un rând complet, inclusiv caracterul 'linie nouă' (engl. newline) de la sfârşitul liniei. 
Dacă este returnat un şir gol (engl. empty), înseamnă că s­a ajuns la sfârşitul fişierului şi ieşim din 
buclă cu declaraţia 'break'. 
Implicit, funcţia print() tipăreste textul şi un caracter newline în mod automat pe ecran. 
Suprimăm caracterul newline automat specificând end='' deoarece linia citită are deja un caracter 
newline la sfârşit. La final închidem fişierul cu close. 
Acum verificaţi conţinutul fişierului poem.txt pentru a confirma că programul a scris întradevăr 
în fişier şi a citit din acesta. 

Conservarea 
Python oferă un modul standard numit pickle (rom. a conserva, a mura) cu ajutorul căruia puteţi 
depozita orice obiect Python întrun fişier pentru a­l reactiva mai târziu. Acest fapt se numeşte 
stocare persistentă. 
Exemplu: 
#!/usr/bin/python
# Fişier: pickling.py

import pickle

# Numele fişierului în care stocăm obiectul


shoplistfile = 'shoplist.data'
# lista de cumpărături
shoplist = ['mere', 'mango', 'morcovi']

# Scriem în fişier
f = open(shoplistfile, 'wb')
pickle.dump(shoplist, f) # depunem (engl. dump) obiectul în fişier
f.close()

del shoplist # distrugem variabila shoplist

# Refacem din depozit


f = open(shoplistfile, 'rb')
storedlist = pickle.load(f) # încărcăm obiectul din fişier
print(storedlist)

Rezultat: 

80
$ python pickling.py
['mere', 'mango', 'morcovi']

Cum funcţionează: 
Pentru a stoca un obiect întrun fişier, trebuie să deschidem fişierul în mod scriere binară ('w' şi 'b') 
cu funcţia open şi să apelăm funcţia dump a modulului pickle. Acest proces se numeşte pickling 
(rom. conservare, figurativ:punere la murat). 
Apoi refacem obiectul folosind funcţia load a modulului pickle, care întoarce obiectul. Acest 
proces se numeşte unpickling (rom. deconservare, figurativ: scoatere de la murat). 

Rezumat 
Am discutat variate tipuri de intrări/ieşiri şi manipularea fişierelor folosind modulul pickle. 
Acum vom studia conceptul de excepţie. 

81
Python ro:Excepţii

Introducere 
Excepţiile pot apărea atunci când apar anumite situaţii excepţionale în program. De exemplu, dacă 
trebuie să citiţi un fişier, dar acesta nu există? Sau dacă l­aţi şters accidental în timpul rulării 
programului? Astfel de situaţii sunt tratate folosind excepţii. 
Similar, daca în program erau câteva declaraţii invalide? Aceste situaţii sunt tratate de Python care 
ridică mâinile şi vă spune ca există o eroare. 

Erori 
Iată un exemplu simplu de apel al funcţiei print. daca aţi scris greşit Print în loc de print? 
Observaţi majuscula. În acest caz, Python ridică o eroare de sintaxă. 
>>> Print('Hello World')
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
Print('Hello World')
NameError: name 'Print' is not defined
>>> print('Hello World')
Hello World

Observaţi că a fost ridicată o eroare NameError şi a fost indicată poziţia unde a fost detectată 
eroarea. Asta este acţiunea unei rutine pentru tratarea erorii (engl. error handler). 

Excepţii 
Vom încerca (engl. try) să preluăm date de la utilizator. Daţi ctrl-d şi vedeţi ce se întâmplă. 
>>> s = input('Introduceţi ceva --> ')
Introduceţi ceva -->
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
s = input('Introduceţi ceva --> ')
EOFError: EOF when reading a line

Python ridică o eroare numită EOFError ceea ce înseamnă în esenţă că a găsit simbolul end of file 
(care se reprezinta prin ctrl-d) întrun moment în care nu era posibil. 

Tratarea excepţiilor 
Putem trata excepţiile folosind declaraţia try..except. Pe scurt, punem declaraţiile uzuale în 
blocul try şi toate tratamentele de erori în blocul except. 
#!/usr/bin/python
# Fişier: try_except.py

82
try:
text = input('Introduceţi ceva --> ')
except EOFError:
print('De ce îmi dai EOF?')
except KeyboardInterrupt:
print('Aţi anulat operaţia.')
else:
print('Aţi introdus {0}'.format(text))

Rezultat: 
$ python try_except.py
Introduceţi ceva --> # Daţi ctrl-d
De ce îmi dai EOF?

$ python try_except.py
Introduceţi ceva --> # Daţi ctrl-c
Aţi anulat operaţia.

$ python try_except.py
Introduceţi ceva --> # fără excepţii, acum
Aţi introdus fără excepţii, acum

Cum funcţionează: 
Punem toate declaraţiile care ar putea ridica excepţii/erori în blocul try şi apoi punem rutine de 
tratare pentru erorile/excepţiile respective în blocul except. Clauza except poate trata o singură 
eroare sau excepţie specificată, sau o listă în paranteze a excepţiilor/erorilor. Dacă nu sunt date 
nume de erori/excepţii, sunt tratate toate erorile şi excepţiile. 
Reţineţi că trebuie să existe măcar o clauză except asociată cu fiecare clauză try. În caz contrar 
ce înteles are un bloc try? 
Dacă o eroare sau excepţie nu este tratată, este apelată rutina implicită de tratare a limbajului Python 
care pur şi simplu opreşte execuţia programului şi tipăreste pe ecran un mesaj de eroare. Am văzut 
deja asta. 
Mai poate exista şi o clauză else asociată cu un bloc try..except. Clauza else este executată 
dacă nu apare nici o excepţie/eroare. 
În următorul exemplu vom vedea cum să obţinem obiectul excepţie, pentru a­i extrage informaţii 
suplimentare. 

Ridicarea excepţiilor 
Puteti ridica excepţii folosind declaraţia raise şi furnizînd numele erorii/excepţiei şi obiectul care 
urmează a fi aruncat (engl. thrown). 
Eroarea sau excepţia pe care o ridicaţi trebuie să fie o clasă derivată direct sau indirect din clasa 
Exception. 
#!/usr/bin/python
# Fişier: raising.py

class ShortInputException(Excepţie):
'''O clasa de excepţii definită de utilizator.'''
def __init__(self, lungime, minim):

83
Excepţie.__init__(self)
self.lungime = lungime
self.minim = minim

try:
text = input('Introduceţi ceva --> ')
if len(text) < 3:
raise ShortInputException(len(text), 3)
# Alte prelucrări pot continua aici ca înainte
except EOFError:
print('De ce îmi dai EOF?')
except ShortInputException as ex:
print('ShortInputException: Aţi introdus un text de lungime {0}, era necesar
minim {1}'\
.format(ex.lungime, ex.minim))
else:
print('Nu a fost ridicată nici o excepţie.')

Rezultat: 
$ python raising.py
Introduceţi ceva --> a
ShortInputException: Aţi introdus un text de lungime 1, era necesar minim 3

$ python raising.py
Introduceţi ceva --> abc
Nu a fost ridicată nici o excepţie.

Cum funcţionează: 
Aici creăm un tip propriu de excepţie. Acest tip nou de excepţie este numit 
ShortInputException. Are două câmpuri ­ lungime care este lungimea introducerii şi 
minim care este lungimea minimă acceptată de program. 
În clauza except menţionăm clasa de erori care va fi stocată sub numele (engl. as) variabilei 
care va păstra obiectul excepţie. Asta este analog parametrilor şi argumentelor în apelul funcţiei. 
Anume în această clauză except folosim câmpurile lungime şi minim ale obiectului excepţie 
pentru a tipări un mesaj adecvat către utilizator. 

try .. finally 
Să presupunem că vreţi să citiţi un fişier întrun program. Cum vă asiguraţi că fişierul a fost închis 
corect indiferent dacă a apărut sau nu o eroare? Asta se poate face folosind blocul finally. 
Observaţi că puteţi folosi o clauză except împreună cu clauza finally pentru acelaşi bloc try. 
Va trebui să le imbricaţi dacă le vreţi pe amândouă. 
#!/usr/bin/python
# Fişier: finally.py

import time

try:
f = open('poem.txt')
while True: # citirea obişnuită
line = f.readline()
if len(line) == 0:
break

84
print(line, end='')
time.sleep(2) # Ca să ne asigurăm că funcţionează un timp
except KeyboardInterrupt:
print('!! Aţi anulat citirea din fişier.')
finally:
f.close()
print('(Curăţenie: Am închis fişierul)')

Rezultat: 
$ python finally.py
Programming is fun
When the work is done
if you wanna make your work also fun:
!! Aţi anulat citirea din fişier.
(Curăţenie: Am închis fişierul)

Cum funcţionează: 
Facem treburile curente la citirea fişierelor, dar avem o aşteptare de două secunde introdusă arbitrar 
după tipărirea fiecarei linii folosind funcţia time.sleep ca să ruleze mai lent (Python este foarte 
rapid prin natura lui). Când programul încă rulează apasaţi ctrl-c pentru a întrerupe programul. 
Observaţi că este aruncată excepţia KeyboardInterrupt şi programul se încheie. Totuşi, 
înainte ca programul să se încheie, clauza finally se execută şi obiectul fişier este întotdeauna închis. 

Declaraţia with 
Achiziţia unei resurse în blocul try şi eliberarea ei în blocul finally este o schemă obişnuită. 
Din acest motiv există şi o declaraţie with care permite ca această utilizare a resursei să se facă 
într­o manieră mai clară: 
#!/usr/bin/python
# Fişier: using_with.py

with open("poem.txt") as f:
for line in f:
print(line, end='')

Cum funcţionează: 
Rezultatul trebuie să fie la fel ca în exemplul precedent, diferenţa este că acum folosim funcţia 
open cu declaraţia with ­ lăsăm închiderea fişierului să fie făcută automat de declaraţia with
open .... 
Ce se întâmplă în culise este un protocol utilizat de declaraţia with. Ea extrage obiectul întors de 
funcţia open, să­i zicem "fişierul" în acest caz. 
Ea apelează întotdeauna funcţia fişierul.__enter__ înainte de a începe blocul de declaraţii 
pe care îl include şi funcţia fişierul.__exit__ după încheierea blocului de declaraţii. 
Astfel codul care ar fi trebuit să fie scris în blocul finally este înlocuit automat de metoda 
__exit__. Astfel suntem ajutaţi să evităm utilizarea explicită a declaraţiilor try..finally în 
mod repetat. 
Discuţia mai aprofundată a acestui subiect este dincolo de obiectivul acestei cărti, deci vă rog să 
citiţi PEP 343 pentru o explicaţie completă. 

85
Rezumat 
Am discutat utilizarea declaraţiilor try..except şi try..finally. Am văzut cum putem 
crea propriul tip de excepţie şi cum să ridicăm excepţii. 
Vom explora în continuare biblioteca Python standard. 

86
Python ro:Biblioteca Python standard

Introducere 
Biblioteca Python standard conţine un număr uriaş de module utile şi este parte a oricărei instalări 
standard Python. Este important să vă familiarizaţi cu biblioteca standard întrucât multe probleme 
pot fi rezolvate rapid dacă cunoaşteţi plaja de lucruri pe care aceste module le pot face. 
Vom explora câteva module utilizate mai frecvent din această bibliotecă. Detaliile complete (în 
limba engleză) despre biblioteca Python standard pot fi găsite în capitolul 'Library Reference' din 
documentaţia care vine cu instalarea Python. 
Să explorăm cateva module utile. 
Notă 
Dacă aceste subiecte vi se par prea avansate puteţi trece peste acest capitol. Totuşi, vă 
recomand călduros să reveniţi atunci când veţi fi mai familiarizaţi cu folosirea limbajului 
Python. 

Modulul sys 
Modulul sys conţine funcţionalitate specifică sistemului de operare. Am aflat deja că lista 
sys.argv conţine argumentele liniei de comandă. 
Să zicem că vreţi să verificaţi versiunea comenzii Python utilizate, să zicem pentru a vă asigura că 
este cel puţin versiunea 3. Modulul sys dă o astfel de funcţionalitate. 
>>> import sys
>>> sys.version_info
(3, 0, 0, 'beta', 2)
>>> sys.version_info[0] >= 3
True

Cum funcţionează: 
Modulul sys are un tuplu version_info care da informaţia despre versiune. Primul element dă 
versiunea majoră. Noi o putem testa pentru a ne asigura că programul rulează sub versiunea minim 
3.0: 
#!/usr/bin/python
# Fişier: versioncheck.py
import sys, warnings
if sys.version_info[0] < 3:
warnings.warn("E nevoie de Python 3.0 sau ulterior pentru a rula acest
program",
RuntimeWarning)
else:
print('Continuăm normal')

Rezultat: 

87
$ python2.5 versioncheck.py
versioncheck.py:6: RuntimeWarning: E nevoie de Python 3.0 sau ulterior pentru
a rula acest program

$ python3 versioncheck.py
Continuăm normal

Cum funcţionează: 
Folosim alt modul din biblioteca standard, numit warnings (rom. avertizări) folosit pentru a afişa 
utilizatorului avertismente pe ecran. Dacă versiunea Python nu este cel puţin 3, afişăm un 
avertisment corespunzător. 

Modulul logging 
Ce e de făcut dacă vreţi să stocaţi undeva mesaje importante sau de depanare, astfel încât să le 
verificaţi mai târziu ca să analizaţi mersul programului? Cum stocaţi undeva aceste mesaje? Acest 
obiectiv pate fi atins folosind modulul logging (rom. jurnalizare). 
#!/usr/bin/python
# Fişier: use_logging.py
import os, platform, logging

if platform.platform().startswith('Windows'):
logging_file = os.path.join(os.getenv('HOMEDRIVE'), os.getenv('HOMEPATH'),
'test.log')
else:
logging_file = os.path.join(os.getenv('HOME'), 'test.log')

logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s : %(levelname)s : %(message)s',
filename = logging_file,
filemode = 'w',
)

logging.debug("Începutul programului")
logging.info("O prelucrare importantă")
logging.warning("Încheiere")

Rezultat: 
$python use_logging.py
Logging to C:\Users\swaroop\test.log

Dacă verificăm conţinutul fişierului test.log, vom găsi cam aşa: 
2009-02-09 13:18:16,233 : DEBUG : Începutul programului
2009-02-09 13:18:16,233 : INFO : O prelucrare importantă
2009-02-09 13:18:16,233 : WARNING : Încheiere

Cum funcţionează: 
Folosim trei module din biblioteza standard ­ modulul os pentru interacţiunea cu sistemul de 
operare, modulul platform pentru informaţii despre platformă adică sistemul de operare şi 
modulul logging pentru a jurnaliza informaţii. 

88
La început verificăm ce versiune de sistem de operare folosim prin analiza şirului întors de funcţia 
platform.platform() (pentru informaţii suplimentare a se vedea import platform;
help(platform)). Dacă este Windows, determinăm drive­ul pe care se află directoarele 
utilizatorului, directorul în care se găsesc acestea şi numele fişierului în care vom stoca informaţia. 
Combinând aceste trei părţi putem stabili calea întreagă a fişierului. Pentru alte platforme ne trebuie 
doar directorul utilizatorului şi avem calea completă a fişierului. 
Folosim funcţia os.path.join() pentru a reuni aceste trei părţi ale căii. Motivul pentru care 
folosim o funcţie specială în loc de simpla concatenare este garanţia că rezultatul va fi conform 
aşteptărilor sistemului de operare. 
Configurăm modulul logging să scrie toate mesajele întrun format anume, în fişierul specificat. 
În final, putem stoca mesaje pentru debugging, urmărire, avertizare sau chiar mesaje critice. Odată 
ce programul a fost lansat, putem vedea ce s­a întâmplat în program, chiar dacă nu a fost afişat 
nimic pe ecran utilizatorului care a lansat programul. 

Modulele urllib şi json 
Cât de distractiv ar fi dacă aţi putea scrie programe care să dea rezultatul unor căutări pe Internet? 
Ia să vedem. 
Putem face asta folosind câteva module. Întâi modulul urllib pe care îl folosim ca să aducă o 
pagină de pe Internet. Vom folosi motorul de căutare Yahoo! pentru a obţine rezultatele căutării şi 
din fericire el ne va da rezultatele căutării în format JSON ceea ce e uşor de procesat pentru noi 
datorită modulului json din biblioteca standard. 
TODO 
Acest program nu funcţionează încă ceea ce pare a fi o eroare (engl. bug) în Python 3.0 beta 2. 

#!/usr/bin/python
# Fişier: yahoo_search.py

import sys
if sys.version_info[0] != 3:
sys.exit('Acest program necesită Python 3.0 sau ulterior')

import json
import urllib, urllib.parse, urllib.request, urllib.response

# Vă puteţi lua APP ID la http://developer.yahoo.com/wsregapp/


YAHOO_APP_ID =
'jl22psvV34HELWhdfUJbfDQzlJ2B57KFS_qs4I8D0Wz5U5_yCI1Awv8.lBSfPhwr'
SEARCH_BASE = 'http://search.yahooapis.com/WebSearchService/V1/webSearch'

class YahooSearchError(Excepţie):
pass

# Luat de la http://developer.yahoo.com/python/python-json.html
def search(interogare, rezultate=20, start=1, **kwargs):
kwargs.update({
'appid': YAHOO_APP_ID,
'query': interogare,
'results': rezultate,
'start': start,
'output': 'json'

89
})
url = SEARCH_BASE + '?' + urllib.parse.urlencode(kwargs)
result = json.load(urllib.request.urlopen(url))
if 'Error' in result:
raise YahooSearchError(result['Error'])
return result['ResultSet']

query = input('Ce doriţi să căutaţi? ')


for result in search(query)['Rezultat']:
print("{0} : {1}".format(result['Titlu'], result['Url']))

Rezultat: 
TODO 

Cum funcţionează: 
Putem obţine rezultatul căutării de la un anumit website dând şirul după care căutăm, întrun anumit 
format. Trebuie să specificăm mai multe opţiuni pe care le combinăm folosind formatul 
cheie1=valoare1&cheie2=valoare2 care este procesat de funcţia 
urllib.parse.urlencode(). 
De exemplu, deschideţi acest link în browserul web (Internet Explorer sau similar) şi veţi vedea 20 
de rezultate, începând cu primul, după cuvintele "byte of python", şi cu rezultatul în format JSON. 
Facem o conexiune la acest URL folosind funcţia urllib.request.urlopen() şi transmitem 
acea referinţă funcţiei json.load() care va citi conţinutul paginii şi va converti fiecare rezultat 
întrun obiect Python. Apoi ciclăm prin aceste obiecte şi le afişăm utilizatorului. 

Seria Modulul săptămânii 
Sunt multe de explorat în biblioteca standard cum ar fi depanarea, gestiunea opţiunilor liniei de 
comandă, expresiile regulare s.a.m.d. 
Cea mai bună cale de a continua explorarea bibliotecii standard este citirea excelentei serii Modulul 
Python al săptămânii a lui Doug Hellmann. 

Rezumat 
Am explorat o parte din funcţionalitatea multor module din biblioteca Python standard. Este 
recomandat să parcurgeţi documentaţia bibliotecii Python standard pentru a vă face o idee asupra 
modulelor disponibile. 
În continuare vom acoperi diverse aspecte care pot face Python mai complet. 

90
Python ro:Plus

Introducere 
Am acoperit până acum majoritatea aspectelor din Python pe care le veţi utiliza. În acest capitol 
vom mai acoperi câteva aspecte care vor 'rotunji' cunoştinţele voastre despre Python. 

Transmiterea tuplurilor 
V­aţi dorit vreodată să returnaţi mai multe răspunsuri dintro funcţie? Puteţi. Nu trebuie decât să 
folosiţi un tuplu. 
>>> def get_error_details():
... return (2, 'detalii eroarea 2')
...
>>> errnum, errstr = get_error_details()
>>> errnum
2
>>> errstr
'detalii eroarea 2'

Observaţi folosirea formulei a, b = <o expresie> care interpretează rezultatul unei expresii 


ca fiind un tuplu cu două valori. 
Dacă vreţi să interpretaţi rezultatul ca (a, <orice altceva>), trebuie să folosiţi asteriscul, ca 
la parametrii funcţiilor: 
>>> a, *b = [1, 2, 3, 4]
>>> a
1
>>> b
[2, 3, 4]

Asta înseamnă că cea mai rapida cale de a interschimba două variabile în Python este: 
>>> a = 5; b = 8
>>> a, b = b, a
>>> a, b
(8, 5)

Metode speciale 
Există anumite metode, precum __init__ şi __del__ care au semnificaţie specială în clase. 
Metodele speciale sunt folosite pentru a imita anumite comportamente ale tipurilor predefinite. De 
exemplu, dacă vreţi să folosiţi operaţia de indexare x[cheie] pentru o clasă (aşa cum aţi folosi­o 
pentru liste sau tupluri), atunci nu trebuie decât să implementaţi metoda __getitem__() şi 
treaba este făcută. Dacă vă gândiţi, asta face Python pentru însăşi clasa list! 
Câteva metode speciale folositoare sunt listate în tabelul următor. Dacă vreţi să studiaţi toate 

91
metodele speciale consultaţi manualul. 
Metode Speciale 
Nume  Explicaţie 

__init__(self, ...)  Metoda este apelată imediat înainte de returnarea obiectului nou creat. 

__del__(self)  Apelată chiar înainte de distrugerea obiectului 

__str__(self)  Apelată premergător executării funcţiei print sau str(). 

Apelată când se foloseşte operatorul mai mic decât (<). Similar, există 
__lt__(self, altceva) 
metode speciale pentru toţi operatorii(+, >, etc.) 

__getitem__(self, 
Apelată când se foloseşte operaţia de indexare x[cheie]. 
cheie) 

Apelată când se foloseşte funcţia predefinită len() pentru un obiect 
__len__(self) 
secvenţă. 

Blocuri cu o singură declaraţie 
Am văzut că fiecare bloc de declaraţii este separat de celelalte blocuri prin nivelul de indentare. Ei 
bine, acesta este un punct riscant. Dacă blocul de declaraţii conţine o singură declaratie, atunci o 
puteţi specifica pe aceeaşi linie cu declaraţia condiţională sau declaraţia de ciclare. Exemplul 
următor va ajuta la clarificarea problemei: 
>>> indicator = True
>>> if indicator: print 'Da'
...
Da

Observaţi că declaraţia unică este folosită pe loc nu întrun bloc separat. Cu toate că puteţi folosi asta 
pentru a obţine programe mai mici, Eu vă recomand cu tărie să nu folosiţi această scurtătura, cu 
excepţia cazului când verificaţi erorile, în special pentru că va fi mult mai uşor să adaugi o 
declaraţie în plus dacă foloseşti indentarea. 

Formule lambda 
O declaraţie lambda se foloseşte pentru a crea obiecte­funcţie în runtime. 
#!/usr/bin/python
# Fişier: lambda.py

def repetor(n):

92
return lambda s: s * n

dublu = repetor(2)

print(dublu('cuvânt'))
print(dublu(5))

Rezultat: 
$ python lambda.py
cuvântcuvânt
10

Cum funcţionează: 
Folosim o formulă lambda numită repetor pentru a crea funcţii obiect în runtime şi a le returna 
în program. În esenţă, formula lambda primeşte un parametru urmat de o expresie unică ce devine 
corpul funcţiei obiect şi valoarea acestei funcţii este returnată de noua funcţie. Reţineţi că întro 
formulă lambda nu poate fi utilizată nici măcar o declaraţie print, ci numai expresii. 
TODO 
Putem executa o funcţie list.sort() furnizănd o funcţie de comparare generată cu o 
declaraţie lambda? 

puncte = [ { 'x' : 2, 'y' : 3 }, { 'x' : 4, 'y' : 1 } ]


# puncte.sort(lambda a, b : cmp(a['x'], b['x']))

Includeri de liste 
Includerile de liste sunt folosite pentru a deriva o listă nouă dintro listă existentă. Să zicem că avem 
o listă de numere şi vrem să obţinem o listă a numerelor înmulţite cu 2 dar numai dacă numărul este 
mai mare decât 2. Includerile de liste sunt ideale pentru aşa ceva. 
#!/usr/bin/python
# Fişier: list_comprehension.py

lista1 = [2, 3, 4]
lista2 = [2*i for i in lista1 if i > 2]
print(lista2)

Rezultat: 
$ python list_comprehension.py
[6, 8]

Cum funcţionează: 
În acest exemplu derivăm noua listă specificând procesarea necesară (2*i) când condiţia este 
satisfăcută (if i > 2). Observaţi că originalul rămâne neschimbat. 
Avantajul folosirii includerilor de liste este că reduce volumul de declaraţii necesare la ciclarea prin 
elementele listei şi stocarea în altă listă a rezultatelor. 

93
Primirea tuplurilor şi listelor în funcţii 
Există o cale specială de a primi parametri întro funcţie sub formă de tuplu sau dicţionar folosind 
prefixul *, respectiv **. Aceasta este utilă atunci când se primeşte un număr variabil de argumente 
în funcţie. 
>>> def sumadeputeri(putere, *argumente):
... ''' Intoarce suma argumentelor ridicate la o putere dată.'''
... total = 0
... for i in argumente:
... total += pow(i, putere)
... return total
...
>>> sumadeputeri(2, 3, 4)
25

>>> sumadeputeri(2, 10)


100

Deoarece avem prefixul * la variabila argumente, toate argumentele transmise funcţiei sunt 
stocate în argumente ca tuplu. Dacă am fi folosit prefixul **, parametrii suplimentari ar fi fost 
consideraţi perechi cheie/valoare întrun dicţionar. 

Funcţiile exec şi eval 
Funcţia exec se foloseşte pentru a executa declaraţii Python stocate întrun şir sau fişier, nu în 
programul însuşi. De exemplu putem genera în runtime un şir conţinând cod Python şi să îl 
executăm folosind declaraţia exec: 
>>> exec('print("Hello World")')
Hello World

Similar, funcţia eval este folosită ca să evalueze expresii Python valide stocate întrun şir. Iată un 
exemplu simplu. 
>>> eval('2*3')
6

Declaraţia assert 
Declaraţia assert este folosită pentru a afirma ceva. De exemplu dacă sunteţi foarte siguri că aveţi 
cel puţin un element în lista pe care o folosiţi şi vreţi să verificaţi asta prin ridicarea unei erori dacă 
nu e aşa declaraţia assert este ideală în aceasta situaţie. Dacă declaraţia assert dă False, este 
ridicată o excepţie AssertionError. 
>>> list= ['item']
>>> assert len(lista) >= 1
>>> lista.pop()
'item'
>>> lista
[]
>>> assert len(lista) >= 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>

94
AssertionError

Declaraţia assert trebuie folosită judicios. De cele mai multe ori este mai bine să prinzi excepţii 
fie că tratezi problema fie că afişezi un mesaj de eroare şi închizi programul. 

Funcţia repr 
Funcţia repr se foloseşte pentru a obţine o reprezentare canonică a obiectului sub formă de şir. 
Partea interesantă este că veţi avea eval(repr(obiect)) == obiect aproape tot timpul. 
>>> i = []
>>> i.append('item')
>>> repr(i)
"['item']"
>>> eval(repr(i))
['item']
>>> eval(repr(i)) == i
True

În esenţă, funcţia repr se foloseşte pentru a obţine o reprezentare tipăribilă a obiectului. Puteţi 
controla ce returnează o clasă pe care o scrieţi la executarea funcţiei repr definind metoda 
__repr__ în acea clasă. 

Rezumat 
Am mai acoperit câteva facilităţi ale limbajului Python în acest capitol dar încă nu le­am acoperit pe 
toate. Totuşi, la acest nivel am acoperit mare parte din ceea ce veţi folosi vreodată în practică. Asta 
este suficient pentru pornire în orice program doriţi să creaţi. 
Mai departe vom discuta cum să continuăm explorarea limbajului Python. 

95
Python ro:Ce urmează
Dacă aţi citit această carte cu atenţie până acum şi aţi exersat o mulţime de programe, v­aţi 
familiarizat deja cu Python. Probabil aţi scris câteva programe ca să încercaţi diverse idei şi să vă 
exersaţi aptitudinile. Dacă nu aţi făcut aşa, ar trebui. Întrebarea este 'Ce urmează?' 
V­aş sugera să abordaţi această problemă: 
Creaţi­vă propria carte de adrese cu interfaţă la linia de comandă, pe care o puteţi 
răsfoi, puteţi adăuga, şterge, modifica contacte precum prieteni, familie colegi etc. şi 
informaţiile lor precum adresa de e­mail şi numărul de telefon. Detaliile trebuie stocate 
pentru o accesare în viitor. 

Asta este destul de uşor dacă vă gândiţi la ea prin prisma diverselor elemente studiate până acum. 
Dacă încă mai vreţi indicaţii cum să porniţi, iată un pont. 
Pont (nu citiţi) 
Creaţi o clasă pentru a reprezenta o persoană cu informaţiile ei. Folosiţi un dictionar pentru a 
stoca obiectele persoană cu cheie numele lor. Folosiţi modulul pickle pentru a stoca obiectele 
în mod persistent pe harddisc. Folosiţi metodele predefinite ale dicţionarelor pentru a adăuga, 
şterge şi modifica persoanele. 

Odată ce puteţi face asta, puteţi spune că sunteţi programator Python. În acel moment trimiteţi­mi 
un e­mail de mulţumire pentru minunata carte ;­) . Acest pas este opţional, dar recomandat. De 
asemenea, vă rog să luaţi în calcul o donaţie, participarea cu îmbunătăţiri sau voluntariatul la 
traduceri pentru a susţine dezvoltarea continuă acestei cărţi. 
Dacă programul vi s­a părut uşor, iată altul: 
Implementaţi comanda replace. Această comandă va înlocui un şir cu altul întro listă de 
fişiere dată. 

Comanda replace poate fi atât de simplă sau de sofisticată cum vreţi, de la o simplă formulă de 
substituţie de şiruri până la căutarea de scheme (expresii regulare). 
După asta, mai există câteva căi de a vă continua călătoria în Python: 

Coduri exemplificative 
Cea mai bună cale de a învăţa un limbaj de programare este de a citi şi scrie mult cod: 
•  Proiectul PLEAC  
•  Depozitul de cod Rosetta  
•  exemple Python la java2s  
•  Cartea de bucate Python  este o colecţie foarte valoroasă de reţete şi ponturi pentru a rezolva 
anumite tipuri de probleme folosind Python. Astea trebuie citite neapărat de fiecare utilizator 
Python. 

96
Întrebări şi răspunsuri 
•  DA­uri şi NU­uri oficiale Python  
•  FAQ oficial Python  
•  Lista lui Norvig de întrebări rare (engl. Infrequently Asked Questions)  
•  Interviu cu întrebări şi răspunsuri Python  
•  întrebări cu tag 'Python' pe StackOverflow  

Ponturi si smecherii 
(engl. tips and tricks) 
•  Python Tips & Tricks  
•  Advanced Software Carpentry using Python  (rom. Tamplarie software avansata folosind 
Python) 
•  Charming Python  este o serie excelenta de articole in legatura cu Python de David Mertz. 

Carti, documentatii, tutoriale, filmulete 
Urmatorul pas logic dupa cartea aceasta este sa cititi minunata carte a lui Mark Pilgrim Dive Into 
Python (rom Aprofundare in Python) pe care o puteti citi si online. Cartea Dive Into Python 
exploreaza subiecte ca expresii regulare, procesare de XML, servicii web, testari de unitati, etc. in 
detaliu. 
Alte resurse folositoare sunt: 
•  filmulete ShowMeDo pentru Python  
•  filmulete GoogleTechTalks despre Python  
•  Lista de tutoriale Python a lui Awaretek  
•  Zona Python Effbot's  
•  Link­uri la sfarsitul fiecarul mesaj Python­URL!  
•  Documentatii Python  

Discuţie 
Dacă vă încurcă o problemă Python şi nu ştiţi pe cine să întrebaţi, grupul de discuţii 
comp.lang.python este cel mai bun loc de a pune întrebarea. 
Asiguraţi­vă că v­aţi făcut tema încercând întâi să o rezolvaţi singuri. 

Noutăţi 
Dacă vreţi să învăţaţi cele apărute mai nou în lumea Python atunci mergeţi la Planeta oficială 
Python şi/sau Planeta neoficială Python. 

Instalarea bibliotecilor 
Există un număr uriaş de biblioteci open source pe care le puteţi folosi în programe la Indexul 

97
pachetelor Python. 
Pentru a le instala şi utiliza puteţi să folosiţi excelentul utilitar EasyInstall. 

Software grafic 
Să zicem că vreţi sa creaţi propriul program cu interfaţă grafică (GUI) folosind Python. Asta se 
poate face folosind o biblioteca GUI (engl. Graphical User Interface) cu conexiunile ei Python. 
Legăturile sunt ceea ce ne permite să scriem programe în Python şi să folosim biblioteci scrise în C 
sau C++, dar şi în alte limbaje. 
Exista o mulţime de opţiuni de GUI care folosesc Python: 
PyQt 
Aceasta este o conexiune Python pentru kitul de utilitare Qt care este fundaţia pe care este 
construit KDE. Qt este extrem de uşor de folosit şi foarte puternic, în special datorită mediului 
Qt Designer şi uimitoarei documentaţii Qt. PyQt este free dacă vreţi să creaţi software open 
source (licenta GPL) respectiv trebuie să­l cumparaţi dacă vreţi să creaţi soft cu sursele 
protejate (închise). Începând cu Qt 4.5 îl puteţi folosi şi pentru a crea soft non GPL. Pentru a 
începe citiţi tutorialul PyQt sau cartea PyQt. 

PyGTK 
Aceasta este conexiunea Python pentru kitul de utilitare GTK+ care este baza pe care este 
construit GNOME. GTK+ are multe complicaţii în utilizare, dar îndata ce te familiarizezi cu 
el, poţi crea aplicaţii GUI rapid. Mediul Glade de proiectare a interfelelor grafice este 
indispensabil. Documentaţia mai trebuie îmbunătăţită. GTK+ lucrează bine pe Linux, iar 
portarea sa pe Windows este incompletă. Puteţi crea cu GTK+ atât soft open source şi soft 
non­GPL. Pentru a începe citiţi tutorialul PyGTK. 

wxPython 
Acesta este conexiunea Python pentru kitul de utilitare wxWidgets. wxPython are asociată o 
curba de învăţare. Totuşi este foarte portabil şi ruleaza pe Linux, Windows, Mac şi chiar pe 
platforme implantate (engl. embedded). Există multe IDE­uri disponibile pentru wxPython 
care includ medii de proiectare GUI precum SPE (Stani's Python Editor) şi constructorul de 
GUI wxGlade. Puteţi crea cu wxPython atât soft open source şi soft non­GPL. Pentru a începe 
citiţi tutorialul wxPython. 

TkInter 
Acesta este unul din cele mai vechi kituri de utilitare GUI. Dacă aţi folosit IDLE, aţi văzut 
programul TkInter la lucru. Nu are cel mai bun aspect şi atmosferă ci unul de şcoala veche. 
TkInter este portabil şi merge atât pe Linux/Unix cât şi pe Windows. Important, TkInter este 
parte a distribuţiei standard Python. Pentru a începe citiţi tutorialul Tkinter. 

Pentru mai multe opţiuni răsfoiţi pagina wiki GuiProgramming de pe websitul oficial Python]. 

Rezumatul utilitarelor GUI 
Din nefericire nu existp un utilitar GUI standard pentru Python. Eu vp propun sp vp alegeşi una din 
uneltele de mai sus, în funcţie de situaţie. Primul factor este dacă doriţi să plătiţi pentru vreuna din 
uneltele GUI. Al doilea factor dacă vreţi să meargă programul numai pe Windows, numai pe Mac 

98
sau Linux sau pe toate. Al treilea factor, dacă a fost aleasă platforma Linux este dacă sunteţi 
utilizator KDE sau GNOME sub Linux. 
Pentru o analiză comparativă mai detaliată citiţi pagina 26 din Publicaţia Python, Volumul 3, 
Numarul 1. 

Diverse implementări 
De obicei există două părţi ale unui limbaj de programare ­ limbajul şi programele. Un limbaj este 
cum să scriem ceva. Programul este ceea ce se foloseşte pentru a rula programele. 
Pentru a rula programele noastre am folosit software­ul (pe scurt softul) CPython. I se spune 
CPython pentru că este scris în limbajul C şi este interpretorul Python clasic. 
Mai există şi alte softuri care pot rula programe Python: 
Jython 
O implementare Python care rulează pe platforma Java. Asta înseamnă că puteţi folosi 
bibliotecile Java şi clase din Python şi reciproc. 
IronPython 
O implementare Python care merge pe platforma .NET. Asta înseamnă că puteţi folosi 
bibliotecile .NET şi clase din Python şi reciproc. 
PyPy 
O implementare Python scrisă în Python! Acesta este un proiect de cercetare având ca 
obiectiv scrierea unui interpretor care să fie uşor de îmbunătăţit întrucât interpretorul însuşi 
este scris întrun limbaj cu tipuri dinamice (spre deosebire de limbajele cu tipuri statice, 
precum C, Java sau C# în aceste trei implementări) 
Stackless Python 
O implementare Python specializată pentru performanţă orientată pe fir de execuţie. 

Mai există şi altele, precum CLPython ­ O implementare Python scrisă în Common Lisp şi 
IronMonkey care este o portare a IronPython pentru a merge susţinută de un interpretor JavaScript 
ceea ce ar putea însemna că pot fi scrise programe de web­browser ("Ajax") în Python (în loc de 
Javascript). 
Fiecare din aceste implementări are domeniul ei în care este utilă, datorită specializării. 

Rezumat 
Am ajuns la sfârşitul acestei cărţi, dar cum se spune este începutul sfârşitului!. Acum sunteţi un 
utilizator avid de Python şi fără îndoială sunteti gata să rezolvaţi multe probleme folosind Python. 
Puteti să începeţi să automatizaţi calculatorul să facă tot felul de lucruri, de neimaginat până acum 
sau puteţi scrie propriile jocuri şi multe altele. Deci să începem! 

99
Python ro:Apendix FLOSS

Free/Libre and Open Source Software (FLOSS) 
FLOSS este bazat pe conceptul de comunitate care este el însuşi bazat pe conceptul de partajare, în 
particular pe partajarea cunoştinţelor. FLOSS sunt libere pentru utilizare, modificare şi redistribuire. 
Dacă aţi citit deja cartea aceasta, sunteţi deja familiar cu FLOSS întrucât aţi folosit Python tot 
timpul, iar Python este software 'open source'! 
Iată câteva exemple de FLOSS pentru a da o idee despre genul de lucruri pe care le poate crea o 
comunitate care construieşte în comun: 
• Linux. Acesta este un sistem de operare FLOSS Pe care încet, încet îl îmbrăţişează toată 
lumea! El a fost iniţiat de Linus Torvalds pe când era student. Acum este un concurent serios 
pentru Microsoft Windows. [ Nucleul Linux ] 
• Ubuntu. Aceasta este o distribuţie menţinută de o comunitate, sponsorizată de firma 
Canonical şi este cea mai populară distribuţie în zilele noastre. Ea vă permite să instalaţi o 
mulţime de FLOSS disponibile şi toate întro maniera uşor de instalat şi folosit. Mai mult 
decât atât, puteţi restarta calculatorul şi rula Linux de pe un CD! Acest lucru vă permite să 
încercaţi toate facilităţile noului sistem de operare înainte de a­l instala în calculator. 
[ Ubuntu Linux ] 
• OpenOffice.org. Aceasta este o suită de aplicaţii de birou cu editor de text, prezentări, foi de 
calcul şi componente de desenare printre altele. Poate deschide şi edita chiar şi fişiere MS 
Word şi MS PowerPoint cu usurinţă. Rulează pe mai toate platformele. [ OpenOffice ] 
• Mozilla Firefox. Acesta este browserul web al noii generaţii care oferă o adevarată 
competiţie lui Internet Explorer. Este rapid ca fulgerul şi a primit felicitări importante pentru 
facilităţile sale sensibile şi impresionante. Conceptul de extensie permite folosirea oricărui 
fel de plug­in (rom. implant). 
• Produsul său partener Thunderbird (rom. pasărea fulger) este un excelent client de e­mail 
care citeşte e­mailul cât ai clipi. [ Mozilla Firefox, Mozilla Thunderbird ] 
• Mono. Acesta este un soft open source care implementează platforma .NET creată de 
Microsoft. El permite aplicaţiilor .NET să fie create şi să ruleze pe Linux, Windows, 
FreeBSD, Mac OS şi pe multe alte platforme. [ Mono, ECMA, Microsoft .NET ] 
• Serverul web Apache. Acesta este binecunoscutul server web open source. De fapt, este cel 
mai popular server web de pe planetă! El rulează mai mult de jumătate din websiturile 
existente. Da, aşa e ­ Apache susţine mai multe websituri decât toată competiţia la un loc 
(inclusiv Microsoft IIS). [ Apache ] 
• MySQL. Acesta este un server de baze de date open source. Este faimos pentru viteza sa 
fulgerătoare. Este M din faimoasa suită LAMP care rulează majoritatea websiteurilor de pe 
Internet. [ MySQL ] 
• VLC Player. Acesta este un player video care poate reda orice de la DivX la MP3 la Ogg la 
VCD­uri şi DVD­uri şi ... cine zice că open source nu e mişto? ;­) [ VLC media player ] 
• GeexBox este o distributie Linux proiectată să redea filme de îndată ce butezi de pe un CD! 
[ GeexBox ] 

100
Această listă vrea doar să vă faceţi o idee ­ există multe FLOSS excelente, precum limbajul Perl, 
limbajul PHP, sistemul Drupal de management al conţinutului websiturilor, serverul de baze de date 
PostgreSQL, jocul de curse TORCS, KDevelop IDE, playerul de filme Xine, editorul VIM, Editorul 
Quanta+, playerul audio Banshee, programul de editare de imagini GIMP, ... Lista ar putea ţine la 
nesfârşit. 
Pentru a prinde cele mai recente subiecte din lumea FLOSS, accesaţi următoarele websituri: 
•  linux.com  
•  LinuxToday  
•  NewsForge  
•  DistroWatch  
Vizitaţi următoarele websituri pentru informaţii despre FLOSS: 
•  SourceForge  
•  FreshMeat  
Aşadar, înainte în explorarea imensei lumi libere (engl. free) şi deschise (engl. open) FLOSS! 

101
Python ro:Apendix Despre...

Apreciere finală 
Aproape tot softul folosit la crearea acestei cărţi este free şi open source. 

Naşterea acestei cărţi 
În primul draft al ei am folosit Linux Red Hat 9.0 ca bază a mediului meu de lucru şi începând cu al 
şaselea draft Linux Fedora Core 3. 
Iniţial foloseam KWord pentru a scrie cartea (cum am explicat în lecţia de istorie din prefaţă). 

Anii adolescenţei 
Mai târziu am trecut pe DocBook XML folosind Kate, dar l­am considerat greoi. Aşa că am trecut 
la OpenOffice care avea un control excelent al formatării şi al generării de PDF, dar producea 
documente HTML cam ţopăite. 
În final am descoperit XEmacs şi am rescris cartea de la 0 în DocBook XML (din nou) după ce am 
decis că aceasta este soluţia de termen lung. 
În al şaselea draft m­am hotărât să folosesc Quanta+ pentru toata editarea. Foloseam foile de stiluri 
XSL care au venit cu Fedora Core 3 şi fonturile implicite standard. Totuşi, am scris un document 
CSS pentru a da culoare şi stil paginilor HTML. Am scris şi un analizor lexical brut, în Python 
desigur, care aducea evidenţierea automată a sintaxei în toate listingurile. 

Acum 
Pentru acest al şaptelea draft, folosesc MediaWiki ca bază a aranjamentului. Acum editez totul 
online şi cititorii pot citi/edita/comenta direct în situl wiki. 
Încă folosesc Vim pentru editare datorită extensiei ViewSourceWith pentru Firefox care se 
integrează cu Vim. 

Despre autor 
http://www.swaroopch.com/about/ 

102
Python ro:Apendix Istoricul reviziilor
• 1.90 
• 04/09/2008 şi încă evoluează 
• Revenire după un salt peste 3.5 ani! 
•  Updatarea la Python 3.0  
• Rescriere folosind MediaWiki (din nou) 
• 1.20 
• 13/01/2005 
• Rescriere completă folosind Quanta+ pe platforma FC3 cu o mulţime de corecturi şi 
actualizări. Multe exemple noi. Rescris aranjamentul DocBook de la 0. 
• 1.15 
• 28/03/2004 
• Revizii minore 
• 1.12 
• 16/03/2004 
• Adăugiri şi corecturi. 
• 1.10 
• 09/03/2004 
• Alte corecturi dactilo datorate multor cititori utili şi entuziaşti. 
• 1.00 
• 08/03/2004 
• Dupa enorm de mult feedback şi sugestii de la cititori am facut multe modificări la 
conţinut şi corecturi dactilo. 
• 0.99 
• 22/02/2004 
• Adaugăt un capitol nou, despre module. Adăugat detalii despre numărul variabil de 
argumente în funcţii. 
• 0.98 
• 16/02/2004 
• Scris script Python şi foaie de stiluri CSS pentru a îmbunătăţi rezultatul XHTML, 
inclusiv un analizor lexical brut, dar funcţional pentru evidenţierea sintaxei în stil 
Vim în listingurile de programe. 
• 0.97 
• 13/02/2004 
• Alt draft complet rescris, din nou in XML DocBook. Cartea a fost îmbunătăţită 
masiv ­ este mai coerentă şi lizibilă. 
• 0.93 
• 25/01/2004 
• Adăugat discuţia despre IDLE şi altele specifice Windows 
• 0.92 
• 05/01/2004 

103
• Schimbări la unele exemple. 
• 0.91 
• 30/12/2003 
• Corectat dactilo. Improvizat mai multe subiecte. 
• 0.90 
• 18/12/2003 
• Adaugăt încă 2 capitole. Format OpenOffice cu revizii. 
• 0.60 
• 21/11/2003 
• Rescris şi expandat cartea. 
• 0.20 
• 20/11/2003 
• Corectat cateva erori minore şi dactilo. 
• 0.15 
• 20/11/2003 
• Conversie în XML DocBook. 
• 0.10 
• 14/11/2003 
• Draft iniţial editat cu KWord. 

104

S-ar putea să vă placă și