0% au considerat acest document util (0 voturi)
12 vizualizări221 pagini

SlitherÎn Python

Cartea 'Slither în Python' este destinată celor care doresc să învețe programarea și conceptele de bază în știința calculatoarelor, fără a necesita experiență anterioară. Aceasta acoperă fundamentele limbajului Python și introduce concepte esențiale din informatică, subliniind importanța gândirii computaționale și a rezolvării problemelor. Cititorii sunt încurajați să instaleze Python și un editor de text, precum Sublime Text, pentru a începe procesul de învățare.

Tradus de

ScribdTranslations
Drepturi de autor
© All Rights Reserved
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca PDF, TXT sau citiți online pe Scribd
0% au considerat acest document util (0 voturi)
12 vizualizări221 pagini

SlitherÎn Python

Cartea 'Slither în Python' este destinată celor care doresc să învețe programarea și conceptele de bază în știința calculatoarelor, fără a necesita experiență anterioară. Aceasta acoperă fundamentele limbajului Python și introduce concepte esențiale din informatică, subliniind importanța gândirii computaționale și a rezolvării problemelor. Cititorii sunt încurajați să instaleze Python și un editor de text, precum Sublime Text, pentru a începe procesul de învățare.

Tradus de

ScribdTranslations
Drepturi de autor
© All Rights Reserved
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca PDF, TXT sau citiți online pe Scribd

1

Conț inuturi
................................................................................................................................................................ 1
Capitolul 1............................................................................................................................................... 7

Cerinț e preliminare...................................................................................................................................... 7
1.1 Rezultatele învăț ării ș i pentru cine este această carter ......................................................................... 7

1.2 Puț in despre Python ..................................................................................................................... 9


1.3 Programul nostru primul.....................................................................................................................10

Chapter 2 - Integers, Operators and Syntax ...................................................................................11


2.1 Întregi......................................................................................................................................11
2.2 Precedenț a operatorilor...............................................................................................................13

2.3 Sintaxă.........................................................................................................................................13

2.4 Exerciț ii.....................................................................................................................................15


Capitolul 3 - Variabile, Float-uri, Introducere ș i Tipărire...........................................................................16

3.1 - Atribuirea variabilelor.............................................................................................................16

3.2 - Tip de număr zecimals..............................................................................................................20


3.3 - Obț inerea inputului utilizatorului..................................................................................................................21

3.4 - Funcț ia de tipăriren ..................................................................................................................23

3.5 - Exerciț ii..................................................................................................................................24


Capitolul 4 - Control Fluxw ...................................................................................................................26

4.1 - Booleans..................................................................................................................................26
4.2 - ThedacăDeclaraț ie.....................................................................................................................28
4.3 - Thedacă-altfeldeclaraț iet .............................................................................................................30
4.4 - Theelifdeclaraț iet ..................................................................................................................32
4.5 - Înglobatdacădeclaraț ii.............................................................................................................33

4.6 - Exerciț ii..................................................................................................................................33


Capitolul 5 - Buclă ș i Iteraț ies .....................................................................................................35
5.1 -în timp cebuclă..............................................................................................................................35
5.2 - Tipare de buclă...................................................................................................................38
5.3 -pauzăș icontinuă................................................................................................................40
5.4 -în timp ceexemple de bucle..............................................................................................................42
5.5 - Exerciț ii..................................................................................................................................43
Capitolul 6 - Ș iruri.............................................................................................................................45
6.1 - Introducere în strings ..........................................................................................................45

2
6.2 - Funcț ii de string......................................................................................................................46
6.3 - Metode de ș iruri......................................................................................................................47

6.4 - Indexarea ș irurilorg.......................................................................................................................49

6.5 - Imutabilitate...........................................................................................................................51
6.6 - Tăierea ș irurilorg ...........................................................................................................................52

6.7 - Operator de ș iruris .....................................................................................................................54

6.8 - Tipărirea ș i formatarea............................................................................................................55

6.9 - Exerciț ii..................................................................................................................................58


Capitolul 7 - Căutare liniarăh ..................................................................................................................61

7.1 - Ce este căutarea liniară?...........................................................................................................61

7.2 Căutare liniară folosind while........................................................................................................61

7.3 - Exemplus .................................................................................................................................62


7.4 - Exerciț ii..................................................................................................................................63
Capitolul 8 - Listăs..................................................................................................................................67

8.1 - Listă literarăs ...............................................................................................................................67

8.2 - Lista metode ș i funcț iis ..................................................................................................68


8.3 - Indexarea listelor...........................................................................................................................70

8.4 - Referinț e ș i Mutabilitate.......................................................................................................70


8.5 - Operaț iuni cu liste........................................................................................................................74

8.6 - Tăierea listelor...............................................................................................................................74

8.7 - Exerciț ii..................................................................................................................................75


Capitolul 9 - Algoritmi de sortare de bază..............................................................................................79

9.1 - Ce este sortarea? .....................................................................................................................79


9.2 - Selection sort..........................................................................................................................79
9.3 - Sortare prin inserț ie ..........................................................................................................................82

9.4 - Compararea sortării prin selecț ie ș i sortării prin inserț ie...............................................................84

9.5 - Exerciț ii..................................................................................................................................87


Introducere, Fiș iere ș i Procesarea Textului.............................................................................................................88

10.1 - Ce este procesarea fiș ierelor ș i a textului? ..........................................................................................88

10.2 - Modulul Sys....................................................................................................................88


10.3 - Reading from standard input.............................................................................................90
10.4 - Scriere la ieș irea standardt ................................................................................................93
10.5 - Eroare standard......................................................................................................................95

3
10.6 - Deschiderea ș i citirea fiș ierelor.....................................................................................................95

10.7 - Scrierea în fiș iere ș i închiderea fiș ierelor............................................................................................96

10.8 - Punând totul împreună.............................................................................................................98


10.9 - Exerciț ii................................................................................................................................99
Capitolul 11 - bucle for ș i Dicț ionare............................................................................................103
11.1 - bucle for..............................................................................................................................103
11.2 - Dicț ionare.........................................................................................................................105
11.3 - Accesarea dicț ionarului..........................................................................................................106

11.4 - Adăugarea ș i eliminarea intrărilors ..........................................................................................107

11.5 - Operatori ș i metode pentru dicț ionare.....................................................................................108

11.6 - Sortarea dicț ionarelor...........................................................................................................110


11.7 - Exerciț ii..............................................................................................................................111
Capitolul 12 - Funcț ii ș i Module................................................................................................115
12.1 - Ce sunt funcț iile?..........................................................................................................115
12.2 - Definirea propriilor noastre funcț ii..............................................................................................115

12.3 - Argumente ș i parametri.................................................................................................116


12.4 - Domeniul variabilelor...................................................................................................................119

12. 5 - Capcana argumentului mutabil implicit......................................................................................119

12.6 - Ce sunt modulele?...........................................................................................................121


12.7 - Crearea propriilor module...............................................................................................122

12.8 - Exerciț ii..............................................................................................................................123


Capitolul 13 - Căutare binară..............................................................................................................127

13.1 - Joc de ghicit numeree ...................................................................................................127


13.2 - Căutare binară......................................................................................................................128

13.3 - Implementarea Căutării Binareh ............................................................................................130

13.4 - Îmbunătăț irea jocului nostru de ghicit numere..........................................................................131

13.5 Analiza Căutării Binare.....................................................................................................131


13.6 - Exerciț ii..............................................................................................................................133
Capitolul 14 - Gestionarea erorilor............................................................................................................135

14.1 - Generarea Excepț iilor.............................................................................................................135

14.2 - Afirmatii...........................................................................................................................136
14.3 - încearcă ș i exceptă........................................................................................................................137

14.4 - finaly ...................................................................................................................................141

4
14.5 - Exerciț ii..............................................................................................................................142
Capitolul 15 - Mai multe despre tipurile de date..................................................................................................145

15.1 - Tupluri..................................................................................................................................145

15.2 - Sets ......................................................................................................................................147


15.3 - Liste ș i comprihensiuni ale listelor.............................................................................................150

15.4 - Exerciț ii..............................................................................................................................151


Capitolul 16 - Recursie ș i Quicksortt ..............................................................................................154

16.1 - Recursivitaten ............................................................................................................................154

16.2 - Memoizare......................................................................................................................156
16.3 - Partea Quicksort1 .................................................................................................................158
16.4 - Partea Quicksort2 .................................................................................................................160
16.5 - Exerciț ii..............................................................................................................................160
Capitolul 17 - Programare orientată pe obiect (OOP)....................................................................162

17.1 - Clase ș i Obiectes ..............................................................................................................162


17.2 - Definirea unui nou tip..........................................................................................................163

17.3 - Variabila de sinee .................................................................................................................164


17.4 - Exerciț ii..............................................................................................................................166
Capitolul 18 - OOP: Metode Speciale ș i Supraincarcarea Operatorilor...............................................169

18.1 - Metoda __init__()........................................................................................................169


18.2 - Metoda __str__().........................................................................................................170
18.3 - Metoda __len__().........................................................................................................171
18.4 - Supraincarcarea operatorilor.......................................................................................................172

18.5 - Exerciț ii..............................................................................................................................175


Capitolul 19 - OOP: Tipuri de metode ș i modificator de access ...............................................................177

19.1 - Ce sunt metodele de instanț ă?...........................................................................................177

19.2 - Ce sunt metodele de clasă?..................................................................................................177

19.3 - Ce sunt metodele statice?.................................................................................................180

19.4 - Atribute publice, private ș i protejate.............................................................................181


19.5 - Exerciț ii..............................................................................................................................182
Capitolul 20 - Moș tenirea OOP........................................................................................................186
20.1 - Ce este moș tenirea?..........................................................................................................186
20.2 - Clase părinte ș i copil.......................................................................................................186
20.3 - Moș tenire multiplă..........................................................................................................191

5
20.4 - Exerciț ii..............................................................................................................................192
Capitolul 21 - Structuri de Date de Bază................................................................................................195

21.1 - Stiva.............................................................................................................................195
21.2 - Coadae ..........................................................................................................................199
21.3 - Exemplus.............................................................................................................................201
21.4 - Exerciț ii..............................................................................................................................203
Capitolul 22 - Structuri de date mai avansate.............................................................................206

22.1 - Lista Vinculatăs .........................................................................................................................206

22.2 - Arbori de căutare binară (BST-uri)................................................................................................210

22.3 - Exerciț ii..............................................................................................................................218

6
Capitolul 1
Cerinț e preliminare
Există doar două lucruri pe care trebuie să le faci înainte de a citi această carte: a avea
Python instalat pe computerul tău. Nu o să trec prin procesul de a face
Aș adar, am lăsat câteva linkuri mai jos despre cum să-l instalaț i pe orice sistem de operare.
veț i folosi. Vom folosi Python 3.7 pe parcursul acestei cărț i; cu toate acestea, s-ar putea
deja ai Python instalat dacă eș ti pe Mac sau Linux. De asemenea, voi dezvolta pe
Windows 10, dar asta nu ar trebui să facă o diferenț ă.

În al doilea rând, ar trebui să ai un editor de text instalat. Îț i recomand Sublime Text.


deoarece va oferi tot ce avem nevoie pentru a începe. Un link pentru a descărca Sublime Text
este de asemenea legat mai jos.

Python pentru Windows:Cum să configurezi Python pe Windows 10

Python pentru MacOS:Cum să configurezi Python pe MacOS

Python pentru Linux (Ubuntu):Cum să configurezi Python pe Ubuntu

Sublime Text 3:Instalaț i Sublime Text 3

De asemenea, recomand cu căldură să te familiarizezi cu linia de comandă. Acest lucru va fi


fii esenț ial dacă vrei să fii productiv. Ș tiu că am spus că voi dezvolta pe
Windows, dar de asemenea recomand să instalaț i o distribuț ie Linux (Ubuntu este
de obicei o alegere bună pentru începători). Poț i instala asta alături de Windows dacă asta e
ce ai instalat. Toț i dezvoltatorii grozavi cunosc linia de comandă Linux pe dinafară
ș i afară ș i dacă lucrezi în această industrie, se aș teaptă să ș tii asta. Mai jos sunt
câteva linkuri despre cum să instalaț i Ubuntu alături de Windows ș i o introducere pentru ambele
linia de comandă Linux ș i Windows.

Cum să instalaț i Linux alături de Windows:Dual-boot Ubuntu ș i Windows

Introducere în Shell-ul Windows:Introducere în Windows Shell

Introducere în linia de comandă Linux:Introducere în linia de comandă Linux

1.1 Rezultate ale învăț ării ș i pentru cine este această carte

Slither în Python este disponibil gratuit online ș i se adresează oricui doreș te să înveț e.
să programeze sau doreș te să înveț e câte ceva despre ș tiinț a calculatoarelor ș i are puț in
fără cunoș tinț e despre niciuna.

7
Nu este necesară experienț a anterioară în programare sau un fond în ș tiinț a calculatoarelor.
Spre deosebire de orice alte resurse Python pe care le-am găsit (nu că acestea nu ar exista), ele nu
explicaț ionează conceptele importante de informatică, cum ar fi memoria sau „cum funcț ionează calculatoarele

muncă” pe care cred că este esenț ială pentru a deveni un bun programator (având câteva
cunoș tinț ele de bază în informatică pot adesea să te ajute să ieș i din situaț ii ciudate
când programez). În această carte voi acoperi fundamentele Python
limbaj de programare ș i introduce aceste concepte importante din ș tiinț a calculatoarelor
ș i teorii.

Pe scurt, programarea sau codarea este despre a face computerele să facă ceea ce
Vrei, informatica este despre cum o fac computerele. Fiecare merge mână în mână,
te ajută să înveț i mai repede, îmbunătăț eș te înț elegerea ta generală a unei limbi ș i face
să fii un programator mai bun. Această carte îș i propune să facă exact asta prin Python.

O altă abilitate importantă pe care o au toț i marii programatori este rezolvarea problemelor. A fi capabil să
gândeș te-te la o problemă dintr-o perspectivă diferită, descompune-o într-o formă mai uș oară
o problemă mai gestionabilă sau reformularea problemei este extrem de importantă.

A gândi computaț ional este de asemenea important (probabil cel mai important. Cei mai mulț i oameni
eşuează pentru că nu învaţă să gândească computaţional). Ia în considerare să faci o ceaşcă de ceai.
Este ceva ce facem în fiecare zi fără a ne gândi prea mult. Cu toate acestea, asta nu va ...
funcț ionează bine pentru noi când vine vorba de scrierea programelor de calculator. Trebuie să împărț im
probleme împărț ite într-un set de paș i bine definiț i.

[Link] a cup of tea:


2.- Fierbe apa
3.- Ia o cană din dulap
4.- Ia un plic de ceai din dulap
5.- Pune plicul de ceai în cea ș că
6.- Pune apă în cea ș că
7.- Dacă vrei zahăr:
8. Ia zahărul din dulap
9. Pune zahărul în ceaș că
10.-Amestecă ceaiul
11.- Îndepărtează plicul de ceai
12.- Dacă vrei lapte:
13. Ia laptele din frigider
14. Toarnă lapte în ceaș că
15.- Stir the tea
16.- Bea ceai

(Vă rog să nu-mi trimiteț i e-mailuri despre metoda mea de preparare a ceaiului!).

Voi explica totul foarte simplu la începutul cărț ii ș i treptat


deveniț i mai tehnic pentru a nu vă copleș i la început (am găsit asta
a funcț ionat bine pentru mine când învăț am să programez).

Sper că până la sfârș itul acestei cărț i veț i avea o înț elegere solidă a Python
limbaj de programare, o înț elegere fermă a informaticii importante

8
concepte, capacitatea de a utiliza tehnicile de rezolvare a problemelor în mod eficient ș i cele mai.
în mod important, gândeș te computaț ional.

1.2 Un pic despre Python


Python este un limbaj de programare interpretat, de nivel înalt ș i de uz general. Acum
s-ar putea să te întrebi ce înseamnă toate acestea, aș a că permite-mi să explic. Un interpretat
limba este o limbă în care nu trebuie să compilăm un program înainte de a-l rula
Compilarea este procesul de traducere a codului pe care îl scriem în cod de maș ină (A
limbajul pe care computerul îl poate înț elege). Cu limbaje interpretate, practic
generaț i codul maș ină pe măsură ce programul nostru rulează (în timpul execuț iei). Acest lucru se face cu
ajutorul unui interpreter. Interpreterul Python este pur ș i simplu numitpython.

Un nivel înalt înseamnă că suntem abstraș i de detaliile computerului. Pentru


în scopuri de explicaț ie, un limbaj de nivel scăzut precum Assembly este utilizat în domenii specializate

aplicaț ii precum sistemele de operare (De fapt, Computerul de Ghidare Apollo 11


a fost scris în limbaj de asamblare ș i codul sursă poate fi găsit aici:Apollo 11 Sursa
Cod). Mai jos este un fragment din acest limbaj de asamblare de nivel scăzut pe care îl vom rescrie
în Python în secț iunea următoare.

[Link] .DATE
2. hello: Salut lume!
3. helloLen: echiv $-hello
4.
[Link] .TEXT
6. GLOBAL _start
7.
8._start:
9. mută eax,4
10. mută ebx,1
11. mută ecx, salut
12. mov edx,helloLen
13. int80h
14.
15. mută eax,1
16. mută ebx,0
17. int80h

Python este adoptat pe scară largă de universităț i din întreaga lume ca


limbaj introdus predat studenț ilor de prim an la informatică datorită
simplicitate. Prin a spune asta, poate fi un limbaj uș or de înț eles ș i uș or de scris
limbaj, dar este de asemenea extrem de puternic. Este folosit peste tot de la automatizarea
sarcinile de calcul zilnic la analiza datelor ș i inteligenț a artificială.

Python are o comunitate imensă în spatele său. Dacă te blochezi într-o problemă sau nu poț i rezolva
sensul unui mesaj de eroare, pot garanta că vei găsi răspunsul tău în decurs de
minute.

9
Python are de asemenea un număr ridicol de mare de biblioteci open source, cadre ș i
module disponibile pentru a face orice doriț i să faceț i. Acest lucru face ca dezvoltarea dvs.
aplicaț iile ș i mai simple.

Pentru a încheia, dacă plănuieș ti să îț i construieș ti o carieră din asta, salariul mediu
pentru un dezvoltator Python în SUA este în jur de 92.000 de dolari.

1.3 Primul nostru program

În secț iunea anterioară am dat peste niș te cod urât în limbaj de asamblare. Acum este
timp să ne scriem primul program. O să traducem acel program în Python:

[Link]("Salut lume!")

Asta e tot! Chiar este atât de simplu. Creează un fiș ier nou în editorul tău de text, copiază textul de mai sus
scrieț i-l în ș i salvaț i-l ca [Link]. Toate programele Python se termină cu extensia .py.

Următorul pas, pentru a rula programul nostru, trebuie să deschidem o fereastră de terminal. Pe Windows, deschide

exploratorul de fiș iere ș i mergi la directorul (folderul) în care ai salvat fiș ierul. În partea de sus
în fereastra explorerului de fiș iere vei vedea ceva similar cu:

Acest PC > Desktop > dosarul_meu

Fă clic pe aceasta ș i scrie „cmd” ș i apasă enter. Aceasta va deschide o fereastră de terminal în acea
director.

În cele din urmă, pentru a rula programul tău, în fereastra terminalului lângă _C:NAME>, tastează
urmat

python [Link]

Ar trebui să vezi acum „Salut lume!” a fost tipărit. Dacă îț i aminteș ti de la


secț iunea anterioară,pythoneste interpretul ș i îi spunem să ruleze programul nostru
'[Link]'

Felicitări! Ai scris primul tău din multe programe Python. Acum vreau să te
să uit programul de mai sus. Îl am aici pur ș i simplu pentru a servi ca un impuls în motivaț ie.
În capitolul următor vom reveni la cele mai de bază noț iuni ș i te vom pune pe drumul cel bun.
pentru a stăpâni limba Python.

10
Capitolul 2 - Numere întregi, Operatori ș i
Sintaxă
2.1 Numere întregi

Înainte să începem, a înț elege materialul din acest capitol este important
totuș i, este foarte uș or! Nu este cu adevărat nimic dificil în acest capitol. Cu toate acestea, eu
voi spune, unele dintre exerciț iile de la final s-ar putea să te surprindă! aș a că fii atent
la conț inut.

Aș a cum am spus la sfârș itul capitolului precedent, uiț i acel program hello world.
În acest capitol vom începe cu cele mai elementare lucruri ș i asta înseamnă
folosind Python ca un calculator de intregi.

În prima parte a acestui capitol, vom folosi ceva numit Python


REPL pentru a scrie programele noastre.

• REPL înseamnă buclă de citire-evaluare-afisare:


oCiteș te o linie de intrare
oEvaluează expresia
oAfiș aț i valoarea rezultată
oBuclă (repeta).

La promptul de comandă (în fereastra terminalului), introduceț i următoarele (apoi


‘Intră’):
python

Ar trebui să vezi ceva de genul:


Python3.7.0 (v3.7.0:1bf9cc5093, 27 iun 2018, 04:59:51) [MSCv.1914 64 biț i
(AMD64)]onwin32
Tipa "ajutor", "drepturi de autor", "merite" sau "licenț ă" pentru mai multe informaț ii.

>>>

Acum să încercăm câteva calcule întregi tastându-le la promptul REPL:


5
5+7
5-3
4*4

11
15//5
5*2+3
3+2*5
(3+2) *5

Acestea sunt cunoscute sub numele de expresii întregi. Ele sunt expresii care evaluează
la o valoare întreagă.
O valoare singulară pe cont propriu, cum ar fi prima expresie din lista de mai sus
expresiile se numesc literal întreg.
Un număr întreg este un număr întreg pozitiv sau negativ.

Deci, ce am învăț at până acum?

• Scriem numere întregi în modul evident


• Am întâlnit câț iva operatori de bază (+, -, * ș i //). Operatorii întregi în acest
caz.
• Folosim * pentru înmulț ire ș i // pentru împărț ire
• Este ceva amuzant în legătură cu * care se întâmplă înainte de +
• De asemenea, folosim (ș i) pentru grupare
• Expresiile întregi se evaluează la valori întregi

De asemenea, putem scrie numere negative în acelaș i mod în care am face-o în mod normal.

5 + -5evaluează la 0.

Pentru completitudine, semnul minus înaintea celui de-al doilea 5 în expresia de mai sus
se numeș te operatorul de negare unară. Acesta acț ionează asupra unei singure valori. Semnul + este un

operator binar deoarece operează asupra a două lucruri numite operanzi (5 ș i -5 în acest
caz).

În programarea computerelor, este foarte important să înț elegi cum să


citeș te-ț i programele în termeni de „părț i de vorbire” ale unui program. Până acum, am avut
următoarele „părț i de vorbire”:

• Literaluriîntregi
• Operatori întregi
oOperatori binari: +, -, * ș i //
oOperatori unari: - (negare)
• Operanzi: 5 + 3
• Expresii întregi

12
• Valori întregi

2.2 Precedenț a operatorilor

Să aruncăm o altă privire asupra unor expresii întregi:

3+2*5
(3+2) *5

Ce ai observat când ai introdus aceste expresii în REPL?

Ei oferă răspunsuri diferite. Aceasta este din cauza a ceva numit precedenț ă.
Precedenț a defineș te ordinea în care operatorii sunt evaluaț i ș i operatorii
sunt evaluate de la cea mai mare prioritate la cea mai mică.

Ordinea de precedenț ă este următoarea:

1.(…)
2. *, /
3. +, -

Aș adar, (…) se întâmplă mai întâi, apoi * ș i //, apoi + ș i -

Pentru completitudine, + ș i - se spune că au o precedenț ă egală. în mod similar, cu *


Cu toate acestea, precedenț a nu ne spune ordinea evaluării pentru
operatori de aceeaș i prioritate ș i poate fi important!
Ceva numit asociativitate determină modul în care operatorii de aceeaș i prioritate
sunt grupate (în absenț a parantezelor).
Operatorii întregi pe care i-am întâlnit sunt asociativi pe stânga, ceea ce înseamnă că sunt

evaluat de la stânga la dreapta.

Pentru a demonstra acest lucru, o expresie precum1 + 2 - 4 + 7 este evaluat ca


urmează:
1+2-4+7
(1+2) -4+7# Evaluează mai întâi 1 + 2
((1+2) -4) +7Evaluaț i 3 - 4 următor
(((1+2) -4) +7-1 + 7

2.3 Sintaxă

13
Acum să aruncăm o cheie în funcț ionare. În REPL-ul Python încearcă acestea
expressions:
4+3+
(1+1))
5+3 2
9+ -3
8+ +9
1* *6

Ai avut prima ta eroare de sintaxă.

În programare, sintaxa unei limbi se ocupă cu modul în care o formulăm


„caracterele” limbii împreună pentru a forma „cuvinte” valide.
O altă modalitate de a privi sintaxa este, setul de reguli care guvernează ceea ce este un
program valid ș i ce nu este.
O eroare de sintaxă apare atunci când nu respectăm aceste reguli (sau formă „fără sens
cuvinte”). Este cam la fel ș i cu limba engleză, de exemplu. Dacă cineva a scris
cuvântul „thwoelaman” probabi că te-ai uita la ei ca ș i cum ar avea două capete
Ș i acesta este, în esenț ă, modul în care interpretul se uită la tine, nu poate face sens
despre ceea ce ai scris!

Pentru expresiile întregi, totuș i, sintaxa este destul de evidentă.

Când scrii cod care nu respectă sintaxa Python ș i primeș ti o


eroare de sintaxă, interpretul python de obicei aruncă o eroare foarte utilă
mesaj. De exemplu, dacă încercăm să evaluăm următoarea expresie:
>>> (1+(//4))

Veț i primi o eroare de sintaxă care arată astfel:


File "<stdin>", line 1
(1 + (// 4))
^
SyntaxError: sintaxă invalidă

Ni se spune că eroul de sintaxă a avut probabil loc pe linia 1. Apoi suntem


arată unde pe linia 1 s-a întâmplat probabil. Acest lucru este arătat prin ^
caracter sub expresia pe care am încercat să o evaluăm. Python este destul de bun la

14
sublinind unde au avut loc aceste erori. De fapt, Python este destul de bun la
indicând unde au avut loc cele mai multe erori în comparaț ie cu multe alte limbi
(cel puț in în opinia mea).
Notă laterală importantă

Vreau să subliniez două alte operaț ii. Operatorul ** (putere) ș i %


(modul) operator.

Funcț ia operatorului de putere (**) este destul de evidentă, dar modulul


operatorul (%), poate nu atât de mult. Încearcă aceste expresii în REPL:

2**2
3**2
4%3
13%10

Aș a este, operatorul % returnează restul după împărț ire. În cazul


din13 % 10, aceasta returnează restul împărț irii lui 13 la 10, care este 3.

2.4 Exerciț ii
Întrebarea 1

• Este operatorul ** (putere) asociativ pe stânga sau pe dreapta? (Încearcă să îț i dai seama de asta)

în REPL)

Întrebarea 2

• Este operatorul % asociativ pe stânga sau pe dreapta? (Încearcă să îț i dai seama de asta în
REPL)

Întrebarea 3

• Unde apar ** ș i % în ierarhia de precedenț ă?

Întrebare 4

• Cum sunt evaluate următoarele expresii?


o1 + 4 - 5 * 7 // 3
o2 ** 3 * 4 + 8 // 3
o4 % 3 ** 5 - 2 ** 2

Întrebarea 5

15
• Din următoarea listă de expresii întregi, care expresie(e) au
Sintaxă invalidă?
o((4 * 6 - (4 // 2))
o9 * -11 + 6
o6 - +4

Capitolul 3 - Variabile, Float-uri, Introducere ș i


Tipărire
3.1 - Atribuirea Variabilelor

În capitolul anterior, am examinat expresiile întregi. Când interpretul


a evaluat o expresie, pur ș i simplu a trecut la următoarea expresie. Ce s-ar întâmpla dacă am
a vrut să stocheze valoarea rezultată? Cum am face asta? Răspunsul este
folosind variabile.

Variabilele utilizează memoria computerului pentru a stoca datele. Poț i gândi


a memoriei principale sau memorie (RAM) ca niș e, fiecare niș ă
etichetaț i cu un identificator (x de exemplu). Când dorim să stocăm o valoare,
practic, spunem computerului să pună o valoare Y în cutiuț a
eticheta x. În Python, aceasta se numeș te asignare de variabile. Să analizăm acest lucru în
acț iune.

1.x = 7
2.y = 5
3.
4.z = x - yValoarea 2 este acum, în esenț ă, stocată în variabila z

Acestea se numesc instrucț iuni de atribuire.

x, y, ș i zsunt variabile.

Sintaxa pentru instrucț iunile de atribuire este:

<variabilă nume> = <valoare pe care vrei să o stochezi>

Pentru această secț iune, cea mai bună alegere ar fi să-ț i deschizi editorul de text ș i un
linie de comandă (fereastră terminal). Creează un fiș ier nou ș i numeș te-l cum vrei
vrei, dar asigură-te că îl salvezi cu extensia .py.
Copiaț i cele trei instrucț iuni de atribuire de mai sus în fiș ier ș i salvaț i-l. Apoi în
în promptul de comandă, rulează programul (python [Link]). Nimic

16
se pare că s-a întâmplat DAR voi ilustra mai jos ce s-a întâmplat în
fundal.

Interpretorul Python consideră fiecare instrucț iune pe rând, de sus în jos,


evaluează expresia din partea dreaptă, alocând o zonă de memorie
pentru noua variabilăxș i stochează valoarea7 în memoria nou alocată
slot. Vom începe cu prima afirmaț iex = 7ș i ia în considerare ce se întâmplă în
memory:
1) Memory:
---------------------------------
# Expresia de pe partea dreaptă este
evaluat
---------------------------------

2) Memory: x
---------------------------------
# Aloca o zonă de memorie pentru x
---------------------------------

3) Memorie: x
---------------------------------

| | | | 7 || | | | # Stochează valoarea 7 în această zonă


al memoriei
---------------------------------

Treceț i la următoarea declaraț ie

Evaluaț i partea dreaptă a


expresie
4) Memorie: x y
---------------------------------
| | | | 7 |# Aloca o zonă de memorie pentru y
---------------------------------

17
5) Memorie: x y
---------------------------------

| | | | 7 || | 5 || # Stochează valoarea 5 în această zonă


de memorie
---------------------------------

Evaluează partea dreaptă a următoarei expresii (z = x - y)


În acest caz, implică variabile, aș a că...
Caută x în memorie ș i înlocuieș te x în expresie cu valoarea
din memorie
(z = 7 - y)
Caută y în memorie ș i înlocuieș te y în expresie cu valoarea
din memorie
(z = 7 - 5)
Evaluează expresia (z = 2)

6) Memorie: x y z
---------------------------------
| | | | 7 || | 5 || # Atribuie o zonă de memorie pentru z

---------------------------------

7) Memorie: x y z
---------------------------------
| | | | 7 || | 5 | 2 | Stochează valoarea 2 în această zonă
de memorie

---------------------------------

Ș i aș a mai departe, executând fiecare instrucț iune de asignare pe rând. Cu toate acestea, am putea

imaginează-ț i că există o altă afirmaț ie care spunex = 9

18
În acest caz, "reciclăm" (sau actualizăm) slotul de memorie, aș a cum se arată mai jos.

1) Memory: x y z
---------------------------------
| | | |*7*| | | 5 | 2 | Memoria a fost deja alocată pentru x,
reutilizaț i-l.

---------------------------------

2) Memory: x y z
---------------------------------

| | | | 9 || | 5 | 2 | Valoarea de la locaț ia de memorie x


este acum 9

---------------------------------

Acum putem folosi acest lucru pentru a face lucruri utile, de exemplu, să calculăm
suprafaț a totală a Pământului (aproximativ).

1.radius_of_earth = 6371
[Link] = 3.14
3.surface_area = 4 * pi * (radius_of_earth ** 2)

NOTĂ IMPORTANTĂ:

• Aceasta mă duce la un punct important. Numele variabilelor tale cu


nume informative precumradius_of_earth este într-adevăr o practică bună, va
îț i va salva multe dureri de cap ș i dacă un alt dezvoltator ar veni
ș i aruncaț i o privire la codul vostru, nu ar fi lăsaț i să se gândească.
capete.
• Este posibil să m-ai fi văzut folosind# pe lângă ceva cod. Acestea se numesc
comentarii. Ele sunt ignorate de interpretul Python ș i sunt acolo
pur ș i simplu pentru beneficiul tău. Este, de asemenea, o bună practică să comentezi codul tău.

Deș i programul de mai sus este simplu ș i nu necesită cu adevărat nicio


comentarii, ai putea să-ț i imaginezi un program care este sute sau mii
de linii lungi (asta e destul de comun) ș i comentariile ar ajuta viitorul
dezvoltatorii care urmau să vină să înț eleagă exact ce face codul tău
încearcă să facă. De asemenea, dacă ai scrie niș te cod, lasă-l pentru un an.
ș i revenind la el, comentariile te ajută să înț elegi ce
am făcut anul trecut.

19
3.2 - Tipuri de puncte flottante

În bucata anterioară de cod despre calcularea suprafeț ei Pământului


s-ar putea să fi observat că am avut declaraț iapi = 3.14

We haven't seen these yet. This is a new type (like integer). They are
numite numere în punct flotant (numere zecimale pentru omul mediu). În
Python, acesta esteplutitortip.
tip(3.14)
<tip'float'>

Floaturile funcț ionează aproape la fel ca ș i integerii (ceea ce sunt sigur că te aș tepț i).
We can perform the same calculations with them. Float expressions also
evaluează la tipuri de float.

>>>2.0//1.0
2.0
>>>2.0*4.0
8.0

# etc....

Nu ș tiu despre tine, dar acel simbol de diviziune pare ciudat. De ce să nu pur ș i simplu
folosiț i un singur/ ?

Ei bine, poț i!// este pentru împărț irea la podea (cifrele după punctul decimal sunt eliminate).
Să ne uităm la cum/ ș i//work:

100//3
33
>>>100/3
33.333333333333336

Putem vedea aici că atunci când folosim întregi,// rotunjeste în jos la un număr întreg
(int) dar când folosim/ rezultatul este convertit într-unplutitorAcesta se numeș te tip
turnare.

În mod similar:
>>>100.0//3.0
33.0

20
>>>100.0/3.0
33.333333333333336

Acesta este ceva la care trebuie să fii atent când faci împărț iri. Dacă tu
foloseș te/ cu operanzi întregi ș i valoarea rezultată conț ine cifre după
loc zecimal, s-ar putea să întâlneș ti o eroare dacă următoarea parte a codului tău este
aș teptând un întreg.
De asemenea, avem toț i ceilalț i operatori standard cu care ne-am întâlnit (operatori float în
acest caz).
De asemenea, putem scrie numere cu zecimale negative în modul aș teptat:

-3.14

3.3 - Obț inerea inputului utilizatorului

Până acum, programele noastre nu au fost chiar atât de interesante ș i nu sunt foarte
benefic. Nu putem interacț iona cu ei când sunt în miș care. Cele mai multe
aplicaț iile în zilele noastre permit utilizatorului să ofere input (fie că este vorba de introducerea

date sau făcând clic pe opț iuni în jurul ecranului). În această secț iune, ne vom uita la
cum poț i obț ine input de la utilizator în timp ce programul tău se execută.

Pentru a face asta, folosim o funcț ie, ș i anumeinput()Vom ajunge la funcț ii mai târziu în aceasta
carte, aș a că nu te îngrijora în legătură cu ele, doar ș tii că atunci când tastăminput(), al nostru

programul va aș tepta ca utilizatorul să introducă ceva la promptul de comandă.

De asemenea, putem stoca introducerea utilizatorului. Acest lucru se face astfel:

>>> x=intrare()
Bună
>>> x
Bună

Implicit,input()returnează un ș ir (str),aia este ceea ce fac ' ' în jurul


Bună emisiuni. Acesta este un alt tip pe care vom ajunge să-l discutăm mai târziu, dar este doar textual.
date (nimic prea înfricoș ător).

Esential, input()prinde o linie din intrare (vom ajunge la asta mai târziu), converteș te
linie într-un ș ir ș i o returnează.

21
Putem vedea că din codul de mai sus ar putea părea că programul nostru are
îngheț at (nu a fost). Putem adăuga un prompt prietenos care să apară când întrebăm
utilizator pentru introducere. Să aruncăm o privire mai atentă la un program mai prietenos cu utilizatorul.

>>> nume=inputIntroduceț i-vă numele:


Introdu numele tău: John

>>> nume

John

Perfect! Acum putem permite utilizatorului să introducă date în programul nostru.

Ce ar fi dacă nu am dori ca utilizatorul să introducă un ș ir? Ce ar fi dacă am dori un integer sau


o plutire?

Există câteva modalităț i de a gestiona această situaț ie, să le examinăm:


# Metoda 1
x=eval(introduceti datele)

Metoda 2
x=int(input())
y=float(introduceț i())

Metoda 1 encapsuleazăintroduceț i() funcț ie într-o altă funcț ie apelatăeval().


eval()este capabil să deducă tipul pe care l-a introdus utilizatorul (dacă utilizatorul introduce 3,
atuncieval()va transforma ș irul '3' într-unintAcelaș i lucru se întâmplă dacă utilizatorul
introduceț i un float. Nu-mi place astaeval()funcț ionează, deș i nu este foarte sigur, dar funcț ionează
bine aici.

Prefer metoda a doua, dar vom avea o eroare ș i programul nostru va


se prăbuș eș te dacă utilizatorul introduce ceva ce nu poate fi convertit într-unintcum ar fi 'salut'.

>>> x=int(introduceț i)
Bună
Urmează urmă (cea mai recentă apelare cea mai recentă):

Fiș ier "<stdin>", linie1, în <modul>


ValueError: literă invalidăforint() cubază10Bună
>>>

22
Primim oValueErrorVom analiza diferitele tipuri de erori puț in mai târziu.
De asemenea, vom analiza capacitatea de a gestiona aceste situaț ii (de aceea prefer
a doua metodă).

3.4 - Funcț ia print


În această secț iune, vom analiza din nou acea funcț ie la care am ajuns.
în secț iunea de introducere unde am scris programul 'Hello world!'.
Pentru a clarifica lucrurile pentru moment, poț i să te gândeș ti la o funcț ie ca la o maș ină care ia

câteva date, face ceva cu acele date, apoi returnează o valoare.

În acest caz,print()ia ceva (un argument) ș i îl printrează în ieș ire


(vom ajunge ș i la asta mai târziu).

Aceasta, în opinia mea, este una dintre cele mai utile funcț ii pe care Python le are de oferit. Ca
progresăm prin această carte ș i lucrurile încep să devină puț in mai dificile, eu
sunt sigur că vei folosi asta destul de mult.

Să aruncăm o privire asupra modului în careprint()funcț ia funcț ionează:

123456>>>print"Bună"

Bună
>>>print(3.14)
3.14
>>>printBună din nou
Bună din nou

Nimic prea complicat! Pentru moment, însă, să recapitulez ce am acoperit.


până acum.

Recapitulare:

• Am descoperit cum să stocăm date în cadrul programului nostru (variabilă


misiune
• Am analizat un nou tip,plutitor.
• Am descoperit că împărț irea poate fi efectuată în două moduri:
• //sau împărț ire prin trunchiere

• / sau
împărț irea ta obiș nuită
• Am învăț at cum să luăm input de la utilizator cuintrare()funcț ie
• Am învăț at cum să imprimăm informaț ii în fereastra terminalului cu
theprint()funcț ie.
23
Să ne uităm la un program care le pune pe toate acestea împreună! (Timp pentru editor de text)

[Link] = input("Care este numele tău? ")


[Link]("Bună " + nume)
[Link]ăr = int(input("Ce număr vrei să fie pătratit? "))
[Link](number ** 2)

În linieprintează("Salut " + nume),+ alătură ș irul "Bună" cu numele


pentru a face un singur ș ir, aceasta se numeș te concatenarea ș irurilor ș i vom ajunge la
acest lucru mai târziu în capitolul despre ș iruri.

3.5 - Exerciț ii
Notă importantă:

Soluț iile pentru unele dintre aceste exerciț ii necesită gândire creativă.
Nu te aș tepta să ajungi imediat la o soluț ie!
Întrebarea 1

Presupuneț i că o populaț ie de iepuri se dublează la fiecare 3 luni. Mai departe presupuneț i că


populaț ia actuală este de 11 iepuri adică.number_of_rabbits = 11

Scrie un program Python pentru a calcula populaț ia de iepuri după 2 ani


ș i imprimă rezultatul în terminal.
Întrebarea 2

Extinde programul de mai sus pentru a permite utilizatorului să introducă numărul de iepuri.

ș i perioada de timp după care vrei să ș tii populaț ia de iepuri, de exemplu 4


years
Întrebarea 3

Presupuneț i că utilizatorul va introduce 2 numere,xș iy de exemplu. Scrie un


Program Python care va schimba numerele stocate în aceste variabile, de exemplu.
# Presupuneț i că utilizatorul a introdus aceste

x=3
y=11
# Codul tău pentru a schimba aici

După, variabilele ar trebui să fie:


# x = 11

#y=3

24
Întrebarea 4

Scopul acestei sarcini este de a deriva o declaraț ie de alocare unică pentru


următoarele secvenț e astfel încât, dacă variabilax are valoarea iniț ială într-un
secvenț ă, apoix va avea următoarea valoare în secvenț ă după atribuire
instrucț iunea este executată. Ș i dacă instrucț iunea de atribuire ar fi fost executată
în mod repetat, apoixar trece prin toate valorile din secvenț ă.

# EXAMPLE

# Secvenț ă:
# 0 1 2 3 4 5 6 7 ...

#SOLUȚ IE
x= x+1

Secvenț a 1:
0 2 4 6 8 10 12 ...

Secvenț a 2:
0-1-2-3-4-5-6 ...

Secvenț a 3:
6-6 6-6 6-6 .....

Secvenț a 4 (Dificil):
-6 -3 0 -6 -3 0 -6 -3 0 -6 -3 0...

25
Capitolul 4 - Flux de control
4.1 - Booleani
Notă importantă:

În acel capitol introduc logica matematică, în special, tabelele de adevăr.


va trebui să aibă o înț elegere solidă a tabelelor de adevăr pentru a putea face
cea mai mare parte a acestui capitol. A avea o înț elegere clară a acestei secț iuni de logică va
de asemenea, te va ajuta să scapi de câteva bug-uri ciudate în programele tale mai departe în
linie.

Dacă poț i să-ț i aminteș ti de exemplul preparării unei ceș ti de ceai, am avut o
pasul care a mers cam aș a:

- dacă vrei lapte:


ia lapte din frigider
toarnă lapte
Fragmentul de mai sus ne-a permis să decidem. În programare, această construcț ie este
fluxul de control. Ori voiam lapte, ori nu. Pentru a implementa
acest tip de lucru în programele noastre trebuie să introducem un nou tip numit
bool care este prescurtarea pentru Boolean.

ABoolean este un tip care are două valori: adevărat sau fals.

>>> tip(True) <clasă 'bool'>

tip(False) <clasă 'bool'>

Acest lucru mă duce la un punct important. În Python, valori diferite ale diferitelor
tipurile pot fi adevărate sau false.

De exemplu, cu numere întregi,0este fals în timp ce orice alt întreg este adevărat. Cu
pluteș te,0.0este fals, în timp ce orice alt float este adevărat ș i, în final, cu stringuri,
empty string ('') este falsă, în timp ce orice altă ș ir de caractere este adevărată.

>>>Fals==0
Adevărat
>>>Fals==1
Fals
>>>Fals==0
Adevărat
>>>False==0.1
Fals

26
De asemenea, putem converti orice altă valoare într-un boolean folosindbool()funcț ia dacă
valoarea poate fi interpretată ca o valoare de adevăr.

Booleanii au, de asemenea, operatori. Aceș tia sunt diferiț i de operatorii pe care i-am văzut.
cu numere întregi ș i zecimale. Acestea sunt operatori Boolean.

Tabelul de adevăr OR

P Q P SAU Q
Adevărat Adevărat Adevărat
Adevărat Fals Adevărat
Fals Adevărat Adevărat
Fals Fals Fals

Ș I Tabelul adevărului

P Q PȘIQ
Adevărat Adevărat Adevărat
Adevărat Fals Fals
Fals Adevărat Fals
Fals Fals Fals

Tabelul adevărului NON

P NU P
Adevărat Fals
Fals Adevărat
Iată câteva exemple în Python
Adevărat sau Adevărat

Adevărat
AdevăratSauFals
Adevărat
FalssauFals
Fals
Adevărat ș iAdevărat
Adevărat
Adevărat ș i Fals
Fals

27
>>> notTrue
Fals
nuFals
Adevărat
Din nou, cunoaș terea acestor tabele de adevăr ca pe dosul mâinii tale este crucială.
Vei face faț ă acestor lucruri foarte des!

4.2 - Instrucț iunea If


În această secț iune, vom analiza adăugarea fluxului de control în programele noastre.
Vom începe prin a privi instrucț iunea if. Înainte de a face acest lucru, vreau să mă uit
la ceva numit operatori de comparaț ie. Aceș ti operatori ne permit să
compara lucrurile.

Operator de comparaț ie Semnificaț ie


== Echivalent cu

!= Nesemnal cu
< Mai puț in decât

> Mai mare decât


<= Mai mic sau egal cu
>= Mai mare sau egal cu
Sunt destul de simple de înț eles, aș a că să le analizăm în acț iune:

>>>1==1
Adevărat
>>>1==2
Fals
>>>10!=4
Adevărat
>>>4!=4
Fals
>>>11>9
Adevărat
>>>13<23
Adevărat
>>>16<2
Fals
>>>13<13
Fals
>>>13<=13
True
Cred că ai înț eles ideea. Aș a că, să trecem la instrucț iunea if.

1.wants_drink = input("Do you want a drink with your meal? (yes or no): ")
2.ifwants_drink =="yes":
3. Aceasta va costa încă 1,50 £
Mul ț umesc! Poftă bună!

28
Dacă executăm codul de mai sus cu două tipuri diferite de intrare, putem obț ine două
rezultate diferite:

# UTILIZATORUL RĂSPUNDE DA
Vrei o băutură cu masa ta? (da sau nu): da
Aceasta va costa un supliment de 1,50 £
Mulț umesc! Poftă bună!

UTILIZATORUL RĂSPUNDE NU
Vrei o băutură cu masa ta? (da sau nu): nu
Mulț umesc! Poftă bună!
Codul de mai sus se citeș te destul de clar, aproape ca în engleză. Dacă utilizatorul spune
da pentru a dori o băutură, apoi imprimă că va costa mai mult.

Sintaxa pentru instrucț iunile if este următoarea:

dacă<CONDI Ț IE>:
Fă ceva dacă condiț ia evaluează la adevărat
Câteva lucruri importante de reț inut despre sintaxă. Este întotdeauna urmat de
condiț ia, apoi un două puncte (::). Pentru blocul de cod care urmează, acesta trebuie să fie
cu indentare!! Îmi place să folosesc taburi, totuș i poț i folosi spaț ii. În acest moment, mă duc
să-ț i spun să alegi un număr de spaț ii. Este obiș nuit să foloseș ti 4 spaț ii. Pentru taburi, 1
tab va fi suficient.

Să vedem un alt exemplu:

1.my_number = int(input("Enter a number: "))


[Link]ă_numărul_meu <= 10:
3. print("Prima linie")
4. print("A doua linie")
5.my_float = 4.3
[Link]("La revedere")

Programul de mai sus nu face nimic util, de fapt este complete gunoi dar este
arată sintaxa pentru instrucț iunile if destul de bine.

Orice lucru care este indentat după declaraț ia if este numit un bloc de cod.
Totul după instrucț iunile if, cum ar fimy_float = 4.3, va fi executat
indiferent denumărul_meufiind mai mic sau egal cu 10.

Probabil că vei face multe greș eli de sintaxă la început, noi toț i am făcut aș a.
nu lăsa să te descurajeze deloc, este complet normal. Chiar ș i cei mai
dezvoltatorii experimentaț i fac greș eli de sintaxă din când în când.

Deș i instrucț iunea if este utilă, ce ne facem dacă ne aflăm într-o situaț ie în care dorim
pentru a face un lucru dacă o condiț ie este îndeplinită, altfel, faceț i altceva? Următorul,
vom examina declaraț ia if-else.

29
4.3 - Declaraț ia if-else
În secț iunea anterioară, am învăț at cum să adăugăm un control de flux foarte basic.
programul nostru, totuș i, ne-am imaginat un scenariu în care am dorit să facem
altceva dacă condiț ia pentru declaraț ia if nu a trecut.

Să vedem cum să facem asta:


1.vârsta_mea = int(input("Introdu vârsta ta: "))
2.
[Link]ă_varsta_mea >= 18:
4. Puteț i intra
[Link]:
6. Eș ti prea tânăr pentru a intra
7.
[Link]("La revedere")

Este din nou destul de uș or de citit programul de mai sus. Când executăm programul de mai sus
programul ar putea avea două ieș iri diferite:

# SCENARIUL 1
Introduceț i-vă vârsta: 33
Puteț i intrare
La revedere

# SCENARIUL 2
Introdu vârsta ta: 14
Eș ti prea tânăr pentru a intra
La revedere
Sintaxa este din nou evidentă:

dacă<CONDI Ț IE>:
Fă ceva dacă condiț ia a fost adevărată
altfel:
Fă ceva diferit!
REAMINTEȘ TEȚI:

Nu uitaț i două puncte la sfârș itul fiecărei afirmaț ii ș i nu uitaț i să indentaț i:


blocul de cod. Fiecare declaraț ie din blocul de cod trebuie să fie de asemenea indentată.
acelaș i număr de spaț ii!

Să privim un alt exemplu. În acest exemplu, dorim să scriem un program care


ne va spune dacă un număr întreg este par sau impar:

[Link] = int(input("Introduceti un numar: "))


[Link]ă(număr % 2) == 0:
3. Numărul tău a fost par
[Link]:
[Link]("Numărul tău a fost impar")

30
Adu-ț i aminte de capitolul despre numere întregi, unde aveam modulul (%) operator?
Pentru a-ț i reîntrema memoria, acest operator a returnat restul după împărț ire.

The== operatorul de comparare ia două operande; în cazul de faț ă, stânga


operandul a fost o expresie. Aceasta va evalua la o valoare care este apoi verificată
pentru a verifica dacă este egal cu zero. Dacă da, atunci este un număr par.

Putem, de asemenea, să combinăm operatorii de comparaț ie ș i operatorii booleani, să ne uităm


la un exemplu despre cum se face asta:

[Link] = int(input("Enter an even number between 50 and 100: "))


[Link]ă(numărul % 2) == 0 ș i numărul < 100 ș i numărul > 50:
3. Aț i introdus un număr par între 50 ș i 100
[Link]:
5. Nu-mi pasă de numărul tău

Condiț ia poate părea urâtă, dar de fapt este destul de uș or de citit:

dacă numărul este par Ș I numărul este mai mic de 100 Ș I numărul este
mai mare de 50"

Putem chiar să-l simplificăm puț in. Îț i aminteș ti că ț i-am spus că valorile ar putea fi adevărate?
sau fals? Ei bine, să ne uităm din nou la programul nostru de numere pare.

1....
2.
[Link]ă (număr % 2) != 0:
4. Numărul tău a fost impar
5. altfel:
6. Numărul tău a fost par.
7.
8....

Reț ineț i că spunem dacă restul nu este egal cu zero în condiț ie.

Am putea simplifica asta la:


[Link]ă numărul % 2:
2. Numărul tău a fost impar
[Link]:
4. Numărul tău a fost par

Dacănumăr % 2este 0, atunci nu intrăm în blocul de cod pentru că 0 este fals.

ÎNDEAMNĂ: Executăm declaraț iile din interiorul blocului if doar dacă


condiț ia evaluează la Adevărat. De asemenea, doar pentru a menț iona, else nu ia o condiț ie. Este
se execută automat dacă condiț ia din declaraț ia if eș uează.

31
4.4 - Declaraț ia If
Programele noastre devin acum un pic mai complexe ș i avem câteva
control decent, dar se comportă ca ș i cum ar exista doar două opț iuni. Ce dacă
au fost 3 sau mai multe opț iuni? Instrucț iunea if-else poate rezolva aceasta pentru noi!

Declaraț ia elif ne permite să verificăm multiple expresii. dacă...elif...altfel


declaraț iile sunt verificate în ordinea secvenț ială, evaluând fiecare condiț ie ș i
execută blocul de cod pentru prima condiț ie care evaluează ca fiind adevărată.

Sintaxa este următoarea:

dacă<condi ț ie1>:
Fă ceva
elif<condi ț ie2>:
Fă altceva
elif<condi ț ie3>:
Fă altceva
.
.
.
elif<condi ț ia N>:
Fă altceva
altfel:
Fă altceva
Putem avea atâtea declaraț ii elif câte ne plac.

Să scriem un program care calculează nota unui student pe baza


mark:

[Link]ă = int(input("Introdu o marcă: "))


2.
[Link]ă nota >= 70:
4. Ai obț inut un loc întâi
5. elifmark >= 50 ș i mark < 70:
[Link]("Ai ob ț inut un al doilea")
[Link] >= 40andmark < 50:
Ai primit un trei
[Link]:
10. Ai eș uat!

Aceste declaraț ii elif sunt destul de clare.

Dacă veniț i dintr-o altă limbă, Python nu oferă


declaraț ii switch/case ca ș i alte limbi, dar putem folosi if...elif...else pentru a
imitaț i-i.

32
4.5 - Instrucț iuni if imbricate

Ce ar fi dacă avem o condiț ie ș i, pe baza acelei condiț ii, trebuie să verificăm


alte condiț ii? Ei bine, putem face asta prin încorporarea declaraț iilor if...elif...else în interior
alte instrucț iuni if...elif...else.

Să ne uităm la un exemplu de program pentru a converti numerele între 0 ș i 3 la


echivalentele lor de cuvinte:

[Link] = int(input("Enter a positive number: "))


2.
[Link]ă numărul >= 0:
4. dacă numărul == 0:
5. Zero
6. elifnumărul == 1:
7. Unu
8. elifnumărul == 2:
9. Două
10. elifnumărul == 3:
11. Trebuie să imprimăm "Trei"
12. altfel:
13. Aț i introdus un număr mai mare decât trei
[Link]:
15. Aț i introdus un număr negativ

Acesta este un exemplu simplu, dar instrucț iunile conditionale îmbinate if...elif...else sunt folosite peste tot.

ș i le vei întâlni frecvent, aș a că petrece timp familiarizându-te cu


scriindu-le!

De asemenea, sunt destul de directe, aș a că o să trec direct la câteva


exerciț ii astfel încât să poț i practica aceste lucruri.

4.6 - Exerciț ii
Notă importantă:

Soluț iile pentru unele dintre aceste exerciț ii necesită să gândeș ti creativ.
Nu te aș tepta să ajungi imediat la o soluț ie!

Întrebarea 1
Scrie un program care ia trei intrări,a, bș icș i afiș ează dacă sau
nu acele numere formează un triunghi dreptunghic. Formula de care vei avea nevoie este

c=(√a2+b2)c=(a2+b2)

33
Întrebarea 2
Fizz buzz este un joc în care se aplică următoarele reguli:

• orice număr care este divizibil cu 3 este înlocuit cufizz


• orice număr care este divizibil cu 5 este înlocuit cuzumzet
• orice număr care este divizibil atât cu 3 cât ș i cu 5 este înlocuit cufizz-buzz
• orice alt număr este doar numărul în sine

Exemple:

1=1
2=2
3 = fizz
4=4
5 = buzz
6=6
.
.
15 = fizz-buzz
* Remember what I said about how if...elif..else statements are evaluated sequentially (first to last) until
prima condiț ie este îndeplinită

În soluț ia ta, ar trebui să te aș tepț i ca utilizatorul să introducă un singur număr ș i


fie imprimă numărul, fie fizz, fie buzz, fie fizz-buzz

Întrebare 3
Scrie un program care primeș te ș ase numere,x1, y1, r1and x2, y2, r2(care sunt
coordonatele x ș i y ale centrului unui cerc ș i raza acestui cerc)
afişează dacă cele două cercuri se suprapun sau nu.

Vei avea nevoie de formula pentru distanț a între două puncte pentru a rezolva
acesta care este:

d(P,Q)=(√(x2−x1)2+(y2−y1)2))d(P,Q)=((x2−x1)2+(y2−y1)2))
Restul necesită o rezolvare a problemei! Poate că desenează scena pe hârtie ar putea
Ajutor?

34
Capitolul 5 - Buclă ș i Iteraț ii
Notă importantă:

Acest capitol poate fi cu mult mai provocator decât capitolele anterioare ș i acolo
este mult de înț eles aici.

5.1 - bucle while


Să zicem că am vrea să facem ceva din nou ș i din nou. În acest moment am avea
să scriem acelaș i cod din nou ș i din nou. Acest lucru nu este practic. Ce s-ar întâmpla dacă
ai vrut să faci ceva de 100 de ori sau de 10.000 de ori?

În acest capitol analizăm buclele ș i iteraț ia, în special bucla while.


buclele sunt sintactic foarte similare cu instrucț iunile if.

# INSTRUCȚ IUNI IF
dacă<condi ț ie>:
Fă ceva
Ș i un alt lucru

BUCLE WHILE
while<condition>:
Fă ceva
Ș i un alt lucru
La fel ca în instrucț iunile if, <condiț ia> este o expresie Boolean. Corpul conț ine de asemenea
o secvenț ă de instrucț iuni. În mod similar, extensia corpului buclei este determinată de
indentarea declaraț iilor.

Modul în care funcț ionează, totuș i, este uș or diferit ș i operează în următorul mod:

1. Evaluează condi ț ia.


2. Dacă condi ț ia evaluează la Fals, atunci sări peste corpul buclei while ș i
execuț i afirmaț iile ulterioare.
3. În alte condi ț ii, dacă condi ț ia evaluează la adevărat:
4. Executa ț i corpul buclei
5. Întoarce ț i-vă la pasul 1.

Permite-mi să ilustrez acest lucru cu un exemplu

1.x = Adevărat # <- Atribuie True lui x (x con ț ine True)


2.în timp ce x == Adevărat: #
3. print("Bună") #
4. x = False #
[Link]("x este acum fals") #
6.
7.-------------------------------------------------------------------------------

35
8.
9.x = Adevărat #
10.în timp ce x ==Adevărat: # <- Evaluează expresia (evaluează la Adevărat)
11. print("Salut") #
12. x = False #
[Link]("x este acum fals") #
14.
15.-------------------------------------------------------------------------------
16.
17.x =Adevărat #
[Link] ==Adevărat: #
19. print("Salut") # <- Afi ș ează "Salut" în fereastra terminalului
20. x = False #
[Link]("x este acum fals") #
22.
23.-------------------------------------------------------------------------------
24.
25.x =Adevărat #
26.în timp ce x ==Adevărat: #
27. print("Salut") #
28. x = False # <- Atribuie False lui x (x con ț ine False)
[Link]("x este acum fals") #
30.
31.------------------------------------------------------------------------------
32.
33.x =Adevărat #
[Link]ă x ==Adevărat: #
35. print("Salut") #
36. x = False # <- Am ajuns la final, a ș a că re-evaluează condi ț ia
[Link]("x este acum fals") #
38.
39.
40.
41.x =Adevărat #
42.între timp x ==Adevărat: # <- Evaluează expresia (e ș uează, deci iese din buclă)

43. print("Salut") # (Dacă nu ar face-o, am merge din nou pe buclă.)


44. x = False #
[Link]ă("x este acum fals") #
46.
47.------------------------------------------------------------------------------
48.
49.x =Adevărat #
[Link] ==True: #
51. Salut #
52. x = False #
[Link]("x este acum fals") # <- Imprimă "x este acum fals" în fereastra terminalului

Să ne uităm la un alt exemplu.

1.i = 0
2.în timp ce i < 5:
3. print(i)
4. i=i+1
5.
6.# IE Ș IREA
7.0
8.1
9.2
10.3
11.4

36
Acest lucru ar putea părea puț in confuz, dar permite-mi să explic ce se întâmplă. Variabila iis
numit un contor (sau o variabilă de bucle) ș i controlează de câte ori se repetă bucla
iterează.

• Variabila este inițial 0, iar condiț ia evaluează ca adevărat, aș a că corpul de


bucla este executată.
• Tipăriț i valoarea variabilei în terminal ș i incrementaț i cu 1. (acum este 1
în loc de 0).
• Evaluate the condition again. It is stillTrueasiis still less than 5.
• Tipăriț i valoarea variabilei în terminal ș i incrementaț i-o cu 1. (este acum
2).
• Repetă paș ii de mai sus până la 5, în care cazul buclei este fals.
bucle se încheie ș i executăm orice instrucț iuni care urmează.

Ce-ar fi dacă am avea condiț ia asi < 10000? Cele patru linii de cod ar rămâne totuș i
ț ineț i apăsat, iar programul va număra de la 0 la 9999.

S-ar putea să te întrebi de ce am numărat de la 0, deoarece pare nenatural, dar există


un motive bune pentru asta. Explicaț ia pentru asta poate fi puț in prea tehnică pentru tine
în această etapă, dar permite-mi să dau un exemplu care, sper, să-l explice.

Îț i aminteș ti că am spus că poț i considera memoria ca pe niste sertare? Ei bine, haideț i să luăm asta

example:

-------------------------------------
| | | | | Fiecare "cubi ț ă" este o *loca ț ie de memorie*
-------------------------------------

-------------------------------------
| | | | | Fiecare are o *adresă*
-------------------------------------

-------------------------------------
| 32 | 44 | 89 | 12 | # Să presupunem că acestea sunt umplute cu valori
-------------------------------------

-------------------------------------
| 32 | 44 | 89 | 12 | # Să spunem că adresa primului
location is 2
-------------------------------------
^
|
2

AVEM NEVOIE DE O FORMULĂ PENTRU A ACCESA LOCATIA DE MEMORIE N DE AICI.


SĂ PRESUPUNEM CĂ VREM SĂ ACCESĂM LOCAȚ IA CARE DEȚ INE 89.
BINE, ACEASTA ESTE: adresa_curentă + 2 (2 + 2 = 4 care este adresa care conț ine
89)

37
# ACEASTĂ FORMULĂ TREBUIE SĂ FIE GENERALĂ, AȘ A CĂ DACĂ AM DORI PRIMA LOCAȚ IE
ACEASTA AR FI: adresa_curentă + 0 (2 + 0 = 2 care este adresa primului
location)
De fapt, nu numărăm de la 0, începem indecș ii (la care vom ajunge mai târziu) cu 0. E...
este doar o practică bună să numărăm de la 0 în bucle ca aceasta, deoarece de obicei folosim o valoare precum
îi indexăm în liste (vom ajunge la acestea mai târziu) ș i recomand să te obiș nuieș ti cu ele acum.
Dacă asta te mai confuzează, va avea sens complet când ajungem la liste puț in mai târziu.
pe.

Este foarte rar să vezi contoare care încep de la ceva de genul 30 ș i unde contoarele fac.
începeț i cu un număr impar sau mare ca acestea, de obicei există un motiv foarte, foarte bun pentru
facând asta.

Să ne uităm la un alt exemplu. Vom scrie un program care permite utilizatorului să introducă 3
numere ș i le vom aduna ș i vom imprima rezultatul.

[Link] = 0
2.
3.i = 0
4.în timp ce i < 3:
5. total = total + int(input())
6. i += 1
[Link](total)

Important: Observaț i cum am scris i += 1. Aceasta este o abreviere pentru i = i + 1. Am fi putut să


de asemenea, a scurtat prima declaraț ie a corpului buclei tototal += int(input()).

5.2 - Modele de repetare


S-ar putea să fi observat în exemplele anterioare de bucle while că aveam o reapariț ie
model (sau structură) pentru buclele noastre.

There are two patterns we usually follow when writingwhileloops. These are:

Fă-ceva-de-n-ori
2. Fă-atâta-timp-cât-nu-este-condi ț ie

Voi ajunge la al doilea model în câteva momente, dar pentru acum voi analiza primul model.

We have been using the first pattern in the previous examples which is as follows:

whilei<N:
Fă ceva
i+=1
În modelul de mai sus, cunoaș tem valoarea lui N înainte de a evalua condiț ia buclelor.
Poate că a venit de la input-ul utilizatorului sau poate fi rezultatul unor anterioare
calcul

38
Ca o convenț ie de denumire, este o practică bună să numeș ti contorul ca ș i cum ar fi ...
folosit ca un nume de variabilă undeva altundeva, atunci jork va face.

Iată un alt exemplu care poate părea că contrazice acest model la o gândire mai atentă
despre problemă, dar ce ar fi dacă am vrea să numărăm invers, aș a că în loc de 0, 1, 2,
am vrut 2, 1, 0 (Probabil te gândeș ti că ar trebui să facem doi = i - 1)?

Iată cum se face, dar utilizatorul introduce numărul de la care numărăm înapoi:

1.n = int(input())
2.
3.i = 0
4.în timp ce i < n:
5. print(n - i - 1)
6. i += 1

Groaznic! Încă ne conformăm modelului.

Să aruncăm o privire asupra celui de-al doilea model de bucle, modelul „Fă-în timp ce-nu-condiț ie”. Cu
nu ș tim de câte ori vom merge în jurul buclei înainte de a
încheie.

Structura sa este următoarea:

în timp ce nu <condi ț ie>:


Fă ceva
Fiecare model are utilizările sale, aș a că să ne uităm la un exemplu unde acest model ar putea fi
folosit.

Presupunem că utilizatorul introduce numere de câte ori doreș te, nu ș tim cât de multe.
încă o dată, iar condiț ia noastră este că nu pot introduce un număr negativ:

[Link] = int(input())
2.
3.în timp ce numărul nu este mai mic decât 0:

4. printaț i(numărul)
5. number = int(input())
[Link]("A ț i introdus un număr negativ")

În acest exemplu, continuăm să cerem utilizatorului un număr ș i îl imprimăm. Continuăm


ca aceasta până când introduc un număr negativ, caz în care condiț ia eș uează ș i
bucla se termină.

Pentru a rezuma:

• Folosim modelul "Fă-ceva-de-N-orii" atunci când ș tim câte ori, noi


trebuie să facem ocolul
• Folosim modelul "Do-while-not-condition" atunci când nu ș tim câte
timpuri, trebuie să facem ocolul

39
Notă importantă:

Dacă foloseș ti modelul "Fă-ceva-N-ori", nu uita să incrementezi!


Omiterea de a incrementa valoarea acestei variabile poate duce la ceva numit
o buclă infinită ș i acestea sunt rele! Dacă faci o buclă de numărare, de exemplu, ca
cel pe care l-am văzut mai sus, ș i tu numeri până la 10 ș i uiț i să incrementezi,
programul tău va număra peste 10 ș i va continua la nesfârș it. Buclele infinite pot duce la
calculatorul tău se aglomerează sau, ș i mai rău, se blochează. Aș adar, fii atent!

5.3 - întrerupere ș i continuare

În aceeaș i secț iune voi discuta despre două noi instrucț iuni. Instrucț iunea break ș i
declaraț ia continuă. Există o mică dezbatere cu privire la când ș i unde ar trebui să
folosiț i-le ș i care este cea mai bună practică în legătură cu utilizarea acestor declaraț ii, dar voi vorbi
despre asta un pic mai târziu în această secț iune.

Instrucț iunea break este folosită pentru a ieș i din buclă sărind peste restul codului buclei.
bloc fără a testa condiț ia pentru buclă.break întrerupe fluxul de
program prin întreruperea buclei ș i continuă să execute restul tău
program.

Instrucț iunea break este utilizată astfel:

while<condi ț ia1>:
# Declaraț ii
dacă<condi ț ie2>:
pauză
# Mai multe declaraț ii
# Restul programului
Iată un exemplu de asta în acț iune:

[Link] = 10
2.
3.i = 0
4.cât timp i < număr:
5. ifi == 5:
6. pauză
7. print(i)
8. i += 1
[Link]("Ie ș irea din program")
10.
11.# IEȘ IRE
12.0
13.1
14.2
15.3
16.4
17. Ieș irea din program

Cred că este destul de auto-explicativ cum funcț ionează break, aș a că să aruncăm o privire la
declaraț ia continuă.

40
Declaraț ia continue este utilizată pentru a sări peste declaraț iile rămase din corpul
loop ș i începe următoarea iteraț ie a buclei. Spre deosebire de
instrucț iunea de întrerupere, continua nu termină bucla, ci pur ș i simplu sare înapoi la
începe.

Declaraț ia continue este folosită astfel:

în timp ce<condi ț ia1>:


Declaraț ii
dacă<condi ț ie2>:
continuare
# Mai multe declaraț ii
# Restul programului tău
Iată un exemplu în acț iune:

[Link] = 5
2.
3.i = -1
4.în timp ce i < număr:
5. i += 1
6. ifi == 2:
7. continua
8. print(i)
[Link]("Ieşirea din program")
10.
11.# IEȘ IRE
12.0
13.1
14.3
15.4
[Link]şirea din program

Observaț i cum acest lucru a deranjat modelul nostru de buclă, deoarece a trebuit să punem i += 1.
prima declaraț ie ș i a trebuit să o iniț ializăm la -1.

Acum acesta este un caz trivial, dar are utilizările sale. Să ne uităm când ș i unde acestea
declaraț iile ar trebui să fie folosite. Deocamdată, totuș i, recomand evitarea lor ș i nu
foloseș te-le ca o cârjă pentru a ieș i dintr-un ciclu. În cea mai mare parte, în această carte, dacă găseș ti
tu însuț i folosind aceste afirmaț ii de obicei există ceva greș it cu bucla ta ș i
ar trebui să te gândeș ti la problemă puț in mai mult.

Când sunt utilizate la începutul unui bloc de cod al unui ciclu, ele acț ionează ca precondiț ii.
precondiț ia este o condiț ie impusă asupra cuiva (ciclul, funcț ia etc.) care trebuie să
se menț ine adevărat la începutul acelui „ceva” pentru a funcț iona corect.

Când sunt plasate la sfârș itul blocului de cod al buclei, acestea acț ionează ca postcondiț ii.
postcondiț ia este o condiț ie impusă asupra unui lucru care trebuie să fie adevărată după
execuț ia acelui „ceva” pentru a fi mulț umit că a fost executat corect.

Acum, acesta următorul ar putea fi puț in confuz, aș a că nu te încurca prea mult în el, eu sunt
Punându-l aici pentru completitudine.

41
Aceste afirmaț ii pot fi folosite ș i ca invarianti, în special, invarianti de buclă. Un
invariant este o afirmaț ie care este plasată într-un segment de cod care este repetat (buclă pentru
exemplu) ș i ar trebui să fie adevărat de fiecare dată despre buclă. Invarianț ii sunt adesea folosiț i în
bucle ș i recursie (despre care vom vorbi mai târziu).

Această parte poate fi confuză. Dacă un invariant este plasat la începutul unui ciclu while
carea condiț iei nu schimbă starea calculului (adică, nu are efecte secundare
efecte), atunci invariantul ar trebui să fie adevărat ș i la sfârș itul buclei. Când este folosit în
programarea orientată pe obiecte (la care vom ajunge mai târziu), invarianț ele pot face referire la
starea unui obiect.

Deocamdată, totuș i, evită-le, în special în exerciț iile de mai târziu.

5.4 -exemple de bucle while


Aș a cum am spus înainte, buclele while pot fi confuze atunci când începi să lucrezi cu ele, aș a că sunt
o să dau câteva exemple suplimentare despre cum acț ionează înainte să trecem la exerciț ii.

Exemplul 1

Primul exemplu de problemă este să verificăm dacă un număr dat este un număr prim, presupunând
numărul dat este mai mare sau egal cu 2. Iată codul:

1.n = int(input())
2.
3.i = 2
[Link] < n ș i (n % i) != 0:
5. i += 1
[Link] < n:
7. Numărul tău nu este un număr prim
[Link]:
9. Numărul tău este un număr prim!

Încercă să înț elegi de ce am instrucț iuni if/else, lucrând la asta pe o foaie de hârtie
cu cifre mici.

Exemplul 2
Următorul exemplu va fi o extensie a programului Fizz-Buzz pe care l-ai
scris înainte. Totuș i, există o mică schimbare. Ultima dată ai scris un program care
afiș ează numărul, fizz, buzz sau fizz-buzz pentru un număr dat. În această rundă, voi merge la
scrie un program care afiș ează secvenț a până la un număr dat.

1.n = int(input())
2.
3.i = 1
[Link] < n:
5. dacă i % 3 == 0 ș i i % 5 == 0:
6. print("fizz-buzz")
7. elifi // 3 == 0:

42
8. print("fizz")
9. elifi // 5 == 0:
10. print("buzz")
11. altfel:
12. print(i)
13. i += 1

Observaț i ordinea în care sunt scrise instrucț iunile if/elif/else. Deoarece în Python instrucț iunile sunt
executate secvenț ial, trebuie să verificăm că numărul nu este divizibil atât cu 3 cât ș i cu
5 mai întâi.

Exemplu 3
În acest program exemplu, vom scrie un program care permite utilizatorului să
introduceț i continuu numere până când introduc numărul 0. Când introduc ei
numărul 0, vom imprima totalul tuturor celorlalte numere pe care le-au introdus.

[Link] = int(input())
2.
[Link] = 0
4.până când numărul nu este 0:
5. total += număr
6. number = int(input())
[Link](total)

Dacă acum te simț i puț in mai confortabil cu buclele while, atunci să aruncăm o privire la câteva
probleme de rezolvat pentru tine!

5.5 - Exerciț ii
Notă importantă:

The solutions to some of these exercises require thinking outside-the-box. Don't


aș teptaț i-vă să ajungeț i la o soluț ie imediat!

Aceste exerciț ii sunt mai dificile, aș a că gândeș te-te cu atenț ie la soluț iile tale.

Întrebare 1
Scrie un program care afiș ează primele n numere din secvenț a Fibonacci.
Secvenț a Fibonacci este definită ca:

Fn=Fn−1+Fn−2, F0=0, F1=1; Fn=Fn−1+Fn−2, F0=0, F1=1

43
Adică, următorul număr din secvenț ă este suma celor două numere anterioare ș i
primele două numere din secvenț ă sunt 0 ș i 1. O parte din secvenț ă este afiș ată
mai jos:

10, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

Întrebare 2
Scrie un program care afiș ează o secvenț ă asemenea celei prezentate mai jos. Numărul de
stelele din partea cea mai lată ar trebui să fie egale cu numărul introdus de un utilizator:

# INPUT
7

# IEȘ IRE
*
**
***
****
*****
******
*******
******
*****
****
***
**
*

Întrebarea 3
Scrie un program Python care citeș te un singur întreg de la utilizator. Apoi citeș te un ...
număr necunoscut de întregi, fiecare dată tipărind dacă numărul a fost sau nu
mai mare sau mai mic decât precedentul. Poț i presupune că fiecare număr este diferit ș i
poț i opri când numărul introdus este 0. Iată un exemplu de input ș i output:

# INPUT
5
2
9
7
0

# OUTPUT
mai jos
mai înalt
mai jos
Ieşire...

44
Capitolul 6 - Ș iruri
6.1 - Introducere în ș iruri
În acest capitol, vom analiza mai bine ș irurile. Ne-am întâlnit cu ele
de mai multe ori în carte ș i ș tim că acestea reprezintă date textuale.

Manipularea datelor textuale este comună în programare, aș a că devenind


a lucra confortabil cu ș iruri este esenț ial!

În Python, reprezentăm ș irurile de caractere ca o secvenț ă de caractere închise între " " sau '
. De exemplu:

1.my_string = hello, world! # This is not a string


2.
3.my_string ="hello, world!" # This is a string!
4.my_string ='hello, world!' # This is also a string!

Python oferă de asemenea un set mare de operaț iuni, metode ș i funcț ii pentru
lucrând cu ș iruri, unele dintre care ne vom întâlni mai târziu în acest capitol.
Lucrul cu ș iruri în Python este de asemenea destul de uș or în comparaț ie cu altele
limbi.

Există câteva lucruri pe care aș dori să le subliniez înainte să trecem la string.


metode. În primul rând, vreau să arunc o privire rapidă asupra funcț iei de imprimare.

print() converteș te fiecare dintre argumentele sale în ș iruri de caractere, introduce un caracter de spaț iu în

ieș irea între fiecare dintre argumentele sale ș i apoi adaugă un caracter de linie nouă
ș i scrie rezultatul în ieș irea standard (în cazul nostru, fereastra terminalului).

Când spun argument, mă refer la următoarele:

print("Aceasta", "şi", "aceea")

IEȘ IRE
„Asta ș i aia”
În codul de mai sus, fiecare dintre ș iruri este un argument ș i poț i avea cât mai multe
atâtea argumente cât vrei (vom examina argumentele în detaliu mai târziu în
capitolul funcț iilor).

Când lucrăm cu date textuale (ș iruri), avem câteva caractere speciale.


Unele dintre acestea sunt:

45
Special CharacterMeaning
\n Linie nouă
\r Întoarcere la linie
Tab
Ș i iată ce fac ei:

Salut Lume
Bună
Lume

Bine ai venit la casa mea


Acasă la mine

Mere Portocale
Mere Portocale
The\t adaugă un tab, acesta\nse va muta pe un nou rând ș i\rva lua esenț ial
orice vine după acesta ș i suprascrie orice vine înaintea lui până la
lungimea oricărui lucru care vine după el. Nu te îngrijora prea mult, am doar
l-am întâlnit de câteva ori.

Probabil nu vom întâlni din nou caracterele tab sau carriage return.
pe parcursul acestei cărț i, dar vreau să te atenț ionez cu privire la caracterul de linie nouă. Doar
pentru că nu poț i vedea asta nu înseamnă că nu este acolo aș a că, dacă te confrunț i vreodată cu
ieș ire neaș teptată caracterul de linie nouă ar putea fi cauza! Dar vom de asemenea
uita-te la cum să te ocupi de asta un pic mai târziu.

Există, de asemenea, un ș ir special numit ș irul gol. Acesta este reprezentat ca "".

6.2 - Funcț ii de ș iruri


Aș a cum am spus anterior, Python oferă o mulț ime de funcț ii pentru a lucra cu
ș iruri, aș a că haideț i să aruncăm o privire asupra unor dintre cele mai importante acum!

MethodWhat it does
len() returnează lungimea ș irului
str() Returnează reprezentarea sub formă de ș ir a unui obiect
chr() Converteș te un întreg într-un caracter
ord() Converte ș te un caracter într-un număr întreg
Să le vedem în acț iune:

>>>len("Bună")
5
>>>len("Salut\nLume") Numărul de caractere newline!
11

46
>>>str(5+5)
10
>>>chr(65)
'A'
>>>ord("B")
66
len() ș i str() funcț ionează aș a cum ne aș teptăm. Convertim un tip într-o ș ir de caractere folosind

funcț ia thestr()

Dar ce fac chr() ș i ord()?

La cel mai elementar nivel, calculatoarele stochează informaț ii sub formă de numere. Pentru a reprezenta

caractere, a fost conceput un sistem de traducere care mapează fiecare caracter


la numărul său reprezentativ.

Cel mai simplu dintre aceste scheme se numeș te ASCII, de care s-ar putea să fi auzit.
reprezintă Codul Standard American pentru Schimbul de Informaț ii ș i acesta acoperă
caracterelor latine obiș nuite cu care probabil eș ti obiș nuit să lucrezi.

chr() ș i ord() sunt folosite pentru a traduce între coduri ș i caractere.

6.3 - Metode de ș iruri


Acum vom analiza metodele de ș iruri. Ele sunt oarecum asemănătoare cu funcț iile
cu excepț ia faptului că sunt specifice pentru ș iruri. De exemplu, len() funcț ionează pe multe

tipuri diferite.

Sintaxa pentru o metodă este următoarea:

[Link]ă(<argumente>)
Să analizăm câteva dintre cele mai frecvent utilizate metode de manipulare a ș irurilor:

Metodă Semnificaț ie
[Link]() returnează o copie a s cu primul caracter scris cu majusculă
[Link]() returnează o copie a s cu prima literă a fiecărui cuvânt capitalizată
[Link]() returnează o copie a s cu to ț i caracterii alfabetici scri ș i cu majuscule
returnează o copie a cărei toate caracterele alfabetice sunt convertite în
[Link]âț eș te()
litere mici
returnează True dacă sis nu este gol ș i toate caracterele sale sunt
[Link]()
alfanumeric (litere ș i cifre) ș i Fals în caz contrar.
returnează True dacă isis nu este gol ș i toate caracterele sale sunt alfabetice
[Link]()
ș i Fals în caz contrar

47
Metodă Semnificaț ie
returnează True dacă sis este non-vid ș i toate caracterele sale pot fi convertite
[Link]() la numere întregi ș i Fals în alte cazuri
returnează o copie a swith cu spaț iul alb pe partea stângă ș i
[Link]()
partea dreaptă eliminată
returnează o copie a lui cu spaț iul alb pe partea stângă
[Link]()
eliminat
returnează o copie a swith cu spaț iul alb pe partea dreaptă
[Link]()
eliminat.
Să ne uităm la acestea în acț iune:

tHiS este A StRIng


>>>[Link]()
Aceasta este un ș ir

Acesta este un ș ir
>>>[Link]()
Aceasta este o ș ir

Aceasta este o ș ir
>>>s.MAI_MARE()
ACEASTA ESTE UN STRING

tHis este A StRInt


>>>[Link]()
aceasta este un ș ir

937 Acesta este un ș ir


>>>[Link]()
Adevărat

93 *** Aceasta este o SIR


>>>[Link]()
Fals

937 Acesta este un ș ir


>>>s.este_alpha()
Fals

Aceasta este o sârmă


>>>[Link]()
Adevărat

Aceasta nu este o cifră


>>>[Link]()
Fals

76324
>>>s.este_cifra()
Adevărat

Aceasta este o ș ir "


>>>[Link]()

48
Aceasta este un ș ir

Aceasta este un ș ir "


>>>[Link]()
Aceasta este un ș ir "

Aceasta este un ș ir "


>>>[Link]()
Aceasta este un ș ir
Pentru unele dintre aceste metode, atunci când nu trecem niciun argument, au un
comportament implicit. Cu toate acestea, putem schimba acest lucru prin transmiterea argumentelor la
funcț ie. Permite-mi să-ț i arăt cum funcț ionează asta:

Aceasta este ș irul meu


>>>[Link]("g")
Aceasta este sârma mea # rstrip() acum elimină 'g' în loc de spaț iu
la partea dreaptă
Asigură-te că te familiarizezi cu acestea, probabil le vei folosi des.
(unii mai des decât alț ii).

6.4 - Indexarea ș irurilor


Notă importantă: Această secț iune este extrem de importantă, aș a că acordaț i-i atenț ie!

Aminteș te-ț i că am vorbit despre memorie ș i numărarea de la 0 pentru indici? Ei bine


Hai să combinăm acele două idei aici.

Am menț ionat mai devreme în capitol că ș irurile sunt o secvenț ă de caractere. În


memoria ele sunt reprezentate ca:

-------------------------------
BUNĂ Fiecare locaț ie de memorie conț ine un caracter
-------------------------------

-------------------------------
BUNĂ Fiecare locaț ie are, de asemenea, o adresă
-------------------------------
| | | | |
13 14 15 16 17 Acestea sunt adrese ipotetice

-------------------------------
BUNĂ Putem obț ine adresa lui 'E' ca 13 + 1
------------------------------- # La fel pentru 'H' ca 13 + 0
| | | | |
13 14 15 16 17

# 0 de mai sus este un „index”, la fel ca 1!

49
Putem indexa ș iruri într-un mod similar! Sintaxa pentru indexarea într-un ș ir este la fel
următoarele:

Bună
>>>s[0]
H
>>>s[1]
e
>>>s[2]
l
>>>s[3]
"l"
>>>s[4]
o
>>>s[5]
Urmează următoarea eroare (cea mai recentă apelare ultima):
Fiș ier "<stdin>", linia 1, în <modul>
IndexError: index de ș ir în afara limitelor
Observaț i că în ultima linie încercăm să indexăm un ș ir la poziț ia 5, dar primim
o eroare de index ș i ni se spune că indexul este în afara intervalului. Aceasta se datorează faptului că noi

începe să numeri de la 0 ș i 0-4 sunt cele 5 indicii ale ș irului.

Deci, indexul final al ș irurilor este:len(s) -1ș i putem indexa folosind


asta:s[len(s) - 1]

Indecș ii de ș iruri pot fi, de asemenea, numere negative ș i vor specifica locaț ii relative
până la sfârș itul ș irului.

Bună
>>>s[-1]
o
>>>s[-2]
l
>>>s[-3]
l
>>>s[-4]
e
>>>s[-5]
H
123B U NĂ # String
0 1 2 3 4 # Indici pozitivi
-5-4-3-2-1 # Negative indices
Recapitulare pentru această secț iune:

• Un index este o poziț ie.


• Folosind indicii, putem face referire la caractere la poziț ii particulare.
• Pentru indice, întotdeauna începem numărătoarea de la 0.
• Primul caracter este la indexul 0.
• Ultimul caracter se află la indexlen(s) - 1

50
6.5 - Imutabilitate
În Python, fiecare variabilă deț ine o instanț ă a unui obiect ș i există două
tipuri de obiecte, mutable ș i imutabile. Până acum, am avut doar
tipuri imutabile, adică întregi, float-uri, bool-uri ș i ș iruri. Un obiect fiind
imitabil înseamnă că valoarea sa nu poate fi schimbată odată creată.

De exemplu, făcând ceva precum:

10=3
True=False
SalutLume
Acest lucru nu ar avea niciun sens ș i e probabil destul de evident de ce. Totuș i,
acum că ș tim despre indexarea ș irurilor, a face ceva precum:

s="string"
s[0]="b"
Aceasta ar putea părea rezonabil. Cu toate acestea, nu este ș i există un motiv bun pentru asta.
Ce ar fi dacă am încerca ceva de genul:

s="string"
s[0]="bl"
Acum, asta ar putea părea razonabil, dar aminteș te-ț i cum sunt stocate ș irurile în
memorie. Când sunt create, au o lungime ș i încercarea de a schimba aceasta
o lungime precum cea de mai sus ar cauza probleme la un nivel inferior (nu că nu ar putea fi...
gata, pur ș i simplu nu merită în 99% din cazuri). Făcând ș irurile de caractere tipuri imutabile
creș te performanț a ș i securitatea, dar nu te îngrijora de asta pentru acum. Doar
ș tii că nu poț i schimba valoarea unui ș ir odată ce a fost creat.

Pentru a înț elege mai bine cum sunt stocate ș irurile în memorie ș i cum
sunt menț ionaț i, uitaț i-vă la codul de mai jos, apoi la diagrama care urmează.

a="Hello"
b=a
a="World"

51
Din prima parte a diagramului, am spus mai devremeunconț ine "Bună", totuș i
asta nu este cazul. Asta a fost pentru simplitate. Ce se întâmplă, de fapt, este că, Python
menț ine un spaț iu de nume de mapări între variabile ș i obiectele la care se referă.
Dupăa = "Hello" este executat, o mapare de laala valoareBunăeste adăugat
în spaț iul de nume.a acum punctează locaț ia din memorie care deț ine valoarea
„Bună”. Spunem căunconț ine o referire la valoareBunăstocat în
memorie.

Când liniab = aeste executat, ceea ce se întâmplă este,bacum indică la acelaș i lucru
locaț ie de memorie carea points to and when a = "World" este executat, un nou
instanț a de ș ir este creată ș i salvată într-o nouă locaț ie de memorie ș i
locaț ie careopunctele sunt actualizate.

Prin urmare, acest comportament este ceea ce face ca ș irurile să fie imutabile. Încercaț i să obț ineț i un

înț elegerea acestui lucru ș i ne vom întoarce la el ș i ne vom uita la el în detaliu.


mai târziu.

6.6 - Tăierea ș irurilor


Am văzut cum să obț inem caracterele de la poziț ii specifice ale unui ș ir folosind
indexare de exemplus[0]obț ine caracterul de la prima poziț ie a ș iruluis.

52
Ce ar fi dacă am dori să obț inem caracterele de la prima la a treia poziț ie a
ș irBunăde exempluHel.

Ei bine, putem! Folosim felierea pentru a face acest lucru. Felierea funcț ionează foarte asemănător cu indexarea.

în schimb, mai degrabă decât să specificăm doar indexul de început, oferim ș i indexul de sfârș it
vrem.

Iată câteva exemple:

Bună
<<<<s[0:3]
Hel

>>>s[0:1]
'H'
Sintaxa este:ș ir[ <început> : <sfârș it> ]

Observaț i cum funcț ionează tăierea. Folosind primul exemplu, tăierea returnează un nou
ș ir cu totul dinsla indexul de început, până la, dar fără a include
indice de sfârș it.

Dacă am vrut totul după prima literă îns, putem omite indexul de sfârș it.
De asemenea, putem omite primul index ș i lăsa indexul final, ceea ce ne va oferi
totul de la indexul 0 până la indexul final specificat

>>>s="Hello"
>s[1:]
salut
>>>s[:3]
Hel
We can also omit both indexes, in which case we'll get the entire string
returned:

Bună
>>>s[:]
Bună
Reț ineț i că două puncte trebuie să rămână în orice caz.

Indiciile pot fi de asemenea variabile:

>>>first=2
>>>last=4
Salut
>>>s[first:last]
'll
Indicii pot fi de asemenea numere negative ș i vor specifica locaț iile în raport cu
sfârș itul ș irului:

53
>>> s = "Hello"
>>> s[:-1]
Iad
>>> s[-4:]
Python oferă, de asemenea, secț ionare extinsă pentru ș iruri. Acest lucru adaugă un al treilea parametru

când se taie ș irul. Acest al treilea parametru indică dimensiunea pasului ș i


sintaxa estes[primul:ultimul:pasul].

Aceasta se face astfel:

Aceasta este un ș ir care trebuie feliat


>>>s[::1]
Aceasta este un ș ir care urmează să fie tăiat
>>>s[::2]
Ti sasrn ob lcd
>>>s[1:8:2]
hsi
Dimensiunea pasului poate fi, de asemenea, negativă (aceasta este utilă pentru a inversa un ș ir)

Aceasta este un ș ir care trebuie tăiat


>>>s[::-1]
Acesta este un ș ir de linii.
>>>s[::-2]
'dcl bo nrsas iT'

6.7 - Operatori de ș iruri


Ș irurile au, de asemenea, operatori. Aceș tia sunt+ operatorul ș i* operator. Ei
nu funcț ionează la fel ca operatorii întregi sau float.

The+ operatorul se numeș te operator de concatenare ș i este folosit pentru a unea ș iruri de caractere
împreună.

>>>s1="Hello"
>>>s2="World"
>>>s1+s2
SalutLume
The* operatorul se numeș te operator de replicare ș i este utilizat pentru a replica un
ș ir.

Bună
>>>s*3
BunăBunăBună
Aceș ti operatori au, de asemenea, o prioritate asociată cu ei:

Aceasta este un ș ir
>>>s+' '*3
Aceasta este un ș ir '
>>> (s + ' ') * 3
Aceasta este un ș ir Aceasta este un ș ir Aceasta este un ș ir

54
Există ș i un alt operator special numitînoperator. Acest lucru va returna un
Boolean bazat pe faptul că un substring este conț inut într-un ș ir.

Aceasta este un ș ir
"Acesta"ins
Adevărat
„ Asta” e
Fals

6.8 - Tipărire ș i formatare


Am privit laprintao funcț ie acum ceva timp. Este destul de simplu în modul în care
funcț ionează. Ia ceva ca argument, încearcă să-l convertească într-un ș ir ș i apoi
o tipă în ieș irea standard (Vom privi ieș irea standard puț in mai târziu, pentru acum
deș i, este doar fereastra terminalului).

Uneori vrem ca rezultatul nostru să arate bine ș i să aibă o lizibilitate mai bună. Să ne
uita-te la un exemplu cu lizibilitate proastă.

1.i = 0
2.în timp ce i < 12:
3. print(i, '* 15 = ', i * 15)
4. i += 1
5.
6.# IE Ș IRE
7.0 * 15 = 0
8.1 * 15 = 15
9.2 * 15 = 30
10.3 * 15 = 45
11.4 * 15 = 60
12.5 * 15 = 75
13.6 * 15 = 90
14.7 * 15 = 105
15.8 * 15 = 120
16.9 * 15 = 135
17.10 * 15 = 150
18.11 * 15 = 165

Putem observa că pe măsură ce numerele devin mai mari în ieș ire, spaț ierea
devine oprit ș i liniile încep să iasă în evidenț ă. Vom analiza cum să facem acest lucru să arate
frumos un pic mai târziu în această secț iune.

Pentru a obț ine o formatare mai bună a ieș irii, folosimformat()operator. Acesta
operatorpreparesa ș ir pentru imprimare.

Sintaxa este următoarea:'{}'.format(x).

Ș irul pe careformatfuncț ionează'{}') se numeș te ș irul format. The{}este


numit un loc de înlocuire sau (câmp de înlocuire). În interiorul locurilor de înlocuire specificăm
cum ar trebui afiș ate datele ș i argumentele pentru metoda format sunt

55
elementele de date care vor fi inserate în fiecare loc de rezervă ș i formatate
conform comenzilor de format ale placeholder-ului.

Sintaxa generală pentru comanda aformat este{[: <aliniere> <lăț ime minimă>
<.precision> <type>]} unde parantezele pătrate indică parametrii opț ionali.

Hai să vedem cum funcț ionează asta în acț iune:

>>>pi=3.14159265359
>>>print('{:.3f}'.format(pi))
3.142
Să descompunem comanda de formatare aici ({:.3f}).

The.3este precizia. În acest caz, dorim ca pi să fie formatat la 3 zecimale


locuri. Thef este tipul care reprezintă tipul de număr cu virgulă mobilă.

Putem avea mai multe locuri de rezervă în ș irul format:

>>>pi=3.14159265359
>>>e=2.71828182845
Numărul pi este: {:.3f} ș i numărul e este {:.5f}
Numărul pi este: 3.142 ș i numărul e este 2.71828
Primul argument care trebuie formatat este asociat cu primul loc de înlocuire ș i
al doilea argument pentru al doilea marcaj ș i aș a mai departe.

Putem avea ș i elemente placeholder înfăș urate:

1.e = 2.71828
2.
3.i = 0
4.în timp ce i < 6:
5. print('{:.{}f}'.format(e, i))
6. i += 1
7.
8.# IE Ș IRE
9.3
10.2.7
11.2.72
12.2.718
13.2.7183
14.2.71828

Placeholder-urile înglobate sunt potrivite de la stânga la dreapta de asemenea. O modalitate de ajutor


a ne gândi la asta înseamnă că, de fiecare dată când întâlnim o acoladă de deschidere, vom
prin introducerea următorului argument.

O altă opț iune pe care o avem pentru comanda format este lăț imea minimă.

Putem folosi această lăț ime minimă pentru a rezolva problema pe care am avut-o cu ieș irea
din tabla înmulț irii cu 15.
56
1.i = 0
2.în timp ce i < 12:
3. print('{:2d} * {:2d} = {:3d}'.format(i, 15, i*15))
4. i += 1
5.
6.# IE Ș IRE
7.0 * 15 = 0
8.1 * 15 = 15
9.2 * 15 = 30
10.3 * 15 = 45
11.4 * 15 = 60
12.5 * 15 = 75
13.6 * 15 = 90
14.7 * 15 = 105
15.8 * 15 = 120
16.9 * 15 = 135
17.10 * 15 = 150
18,11 * 15 = 165

Lăț imea minimă va completa argumentul cu spaț ii libere pentru a


lăț ime minimă specificată.

Observaț i că avemdîn loc def. Acesta înseamnă un număr întreg. De asemenea, nu


specificaț i o precizie care este indicată printr-un. urmat de numărul de precizie.

Putem de asemenea să specificăm un aliniament. Aliniamentele sunt specificate cu^ pentru


centrat< pentru justificare la stânga ș i> pentru justificare dreaptă.

Să ne uităm la exemplul cu stea, aceasta nu este în niciun caz o soluț ie bună, este pur ș i simplu
pentru a arăta utilizarea comenzii de formatare a aliniamentului:

1.i = 0
2.între timp i < 6:
3. print('{:^10s}'.format('* '*i))
4. i += 1
5.
6.i -= 2
7. în timp ce i > 0:
8. print('{:^10s}'.format('* '*i))
9. i -= 1
10.
11.# IEȘ IRE
12. *
13.* *
14.* * *
15.* * * *
16.* * * * *
17.* * * *
18.* * *
19.* *
20. *

După cum puteț i vedea în comanda de formatare, specificăm ș irul care trebuie centrat
cu o lăț ime minimă de 10 ș i tipul să fiescare este un ș ir.

57
6.9 - Exercitii
NOTĂ IMPORTANTĂ:

Nu pot să-ț i arăt tot ce există despre python. Cartea ar continua la nesfârș it.
O abilitate cu adevărat importantă pe care o au toț i programatorii buni este capacitatea de a ș ti ce
să caute atunci când se confruntă cu o problemă pe care nu o pot rezolva singuri. Pentru
de exemplu, s-ar putea să vreau să pot face ceva cu un ș ir, dar nu ș tiu
cum. Ș tiind unde să cauț i pentru a afla răspunsul este foarte important. Tu
s-ar fi putut să fi dat peste un site numit Stack Overflow până acum. Acesta este
va fi o resursă foarte bună pentru tine. Prin urmare, unele dintre întrebările în
aceste exerciț ii pot necesita să cauț i metode care să te ajute
ajungeț i la soluț ia dvs.

Există multe de învăț at din acest capitol. Ș irurile sunt importante ș i sunt folosite în tot timpul
timp. A deveni confortabil cu ele este la fel de important.

Întrebare 1
Scrieț i un program care ia ca input un singur număr întreg de la utilizator care va
specificaț i câte zecimale are numărulear trebui să fie formatat la.

Ia un număr de 2.7182818284590452353602874713527

EXEMPLU DE ÎNTRARE
4
# EXAMPLE OUTPUT
2.7183

Întrebarea 2
Scrie un program care va lua ca input, un ș ir de caractere ș i două numere întregi. Cele două
numerele întregi vor reprezenta indicii. Dacă ș irul poate fi tăiat folosind cei doi indici,
atunci tipăriț i ș irul feliat. Dacă oricare dintre cele două numere întregi este în afara ș irurilor
interval de index, apoi tipăriț i că ș irul nu poate fi tăiat la acele întregi.

Presupuneț i că numerele întregi nu pot fi negative.

# EXAMPLE INPUT
Aceasta este ș irul meu
2
9

# EXAMPLE OUTPUT

58
este asta m'

EXEMPLU DE INPUT
Aceasta este un ș ir
10
22

# EXEMPLU DE IEȘ IRE


Nu se poate tăia ș irul folosind acele indexuri

Întrebarea 3
Când te înscrii pentru conturi pe site-uri web sau aplicaț ii, s-ar putea să ț i se spună că
puterea parolei atunci când o introduceț i pentru prima dată. În acest exerciț iu, sunteț i
să scrieț i un program care ia ca intrare, un ș ir care va reprezenta un
parolă.

Presupuneț i că o parolă poate conț ine următoarele:

• cifre
• litere
mici
• LITERE MARI
• caractere speciale (consideraț i acestea ca fiind: $, #, @ ș i ^)

Punctajul unei parole ar trebui să fie evaluat în funcț ie de câte dintre categoriile de mai sus
sunt conț inute în parolă. Parola ar trebui să primească un scor de la 1 la
4.

Dacă parola este mai mare sau egală cu puterea 3 (conț ine caractere din)
3 dintre categoriile de mai sus) atunci ar trebui să imprimi puterea ș i că
parola este validă. În caz contrar, afiș aț i puterea ș i că parola nu este
valid.

Python vine cu documentaț ie încorporată. Pentru a accesa aceasta, la comanda


tip de promptpydoc strAcesta va returna documentaț ia pentrustrtip.
Aici veț i găsi toate metodele pe care ș irurile le au de oferit.

# EXEMPLES DE ENTRÉES
978
hjj
jKl
nmM2
r@num978LL
LLLL

# EXAMPLE OUTPUTS
1

59
1
2
3
4
1

Întrebarea 4
Scrie un program care ia 3 numere cu virgulă mobilă ca input de la utilizator: a
raza de început, incrementul razei ș i o rază de sfârș it. Pe baza acestor trei
numere, programul tău ar trebui să afiș eze un tabel cu sfere corespunzătoare
suprafaț ă ș i volum.

Suprafaț a ș i volumul unei sfere sunt date de următoarele formule:

A = 4πr2A = 4πr2

V=43πr3V=43πr3

Sfat: Formatarea este cheia aici

EXEMPLU DE INTRARE
1
1
10
# EXEMPLU DE IEȘ IRE
Radii Arie Volum
---------- ---------- ------------
1.0 12.57 4.19
2.0 50.27 33.51
3.0 113,10 113.10
4.0 201.06 268.08
5.0 314,16 523,60
6.0 452,39 904.78
7.0 615.75 1436.76
8.0 804.25 2144.66
9.0 1017.88 3053,63
10.0 1256.64 4188.79

60
Capitolul 7 - Căutare liniară
7.1 - Ce este căutarea liniară?
În acest capitol vei codifica primul tău algoritm. Vom analiza
algoritmul de căutare liniară.
Căutarea liniară (sau căutarea secvenț ială) este o metodă de a găsi un element în
ceva. Acea ceva poate fi un ș ir, un fiș ier sau o listă. Elementul pe care îl suntem
caută orice ar putea fi (o literă, un număr, un cuvânt, etc).

(De obicei) căutăm poziț ia elementului dorit. Prin urmare,


în unele cazuri, elementul pe care îl căutăm poate să nu existe ș i avem nevoie
algoritmul nostru să fie capabil să facă faț ă acestuia.

Căutarea liniară este utilizată frecvent în informatică ș i este un algoritm uș or.


să înț elegem ș i să scriem ș i este perfect pentru noi în această etapă.

7.2 Căutare liniară folosind while

În termeni tehnici, căutăm poziț ia unui anumit element Q care


satisface o oarecare proprietate P.

În cazul general, putem realiza acest lucru după cum urmează:

eu=0
în timp ceeu< Nș i nuP:
eu+=1

Ceea ce ne dorim este poziț ia elementului Q care satisface anumite


proprietatea P aș a că continuăm să căutăm atâta timp cât acea proprietate P nu este satisfăcută
ș i ne oprim când este.
Să vedem un exemplu pentru a ajuta la clarificare. În acest exemplu, dorim să găsim...
poziț ia primei apariț ii a literei "W":

1.s ="Hello World"


2.
3.i = 0
4.în timp ce i < len(s) ș i s[i] != "W":
5. i += 1

Ce facem aici este să începem de la index 0 ("H") ș i să continuăm prin ș irul de caractere,
verificând fiecare index până când se găseș te 'W' ș i aceasta este căutarea liniară.

61
Acum avem o altă problemă. Există două condiț ii în bucla while.
Fie "W" este găsit ș i ieș im din buclă, fie căutăm întreaga ș ir de caractere ș i
"W" nu a fost găsit. Cum ș tim ce condiț ie a cauzat loop-ul să
termina?

Dacă condiț ia 1 (i < len(s)) esteAdevaratatunci "W" a fost găsit deoarece clar nu am
ajunge la sfârș itul ș irului SAU condiț ia 1 esteFalsîn care am ajuns
sfârș itul ș irului ș i "W" nu a fost găsit.

Putem verifica asta simplu:

1.s ="Hello World"


2.
3.i = 0
4. în timp ce i < len(s) ș i s[i] != "W":
5. i += 1
6.
7. dacă < len(s):
8. Litera 'W' a fost găsită la poziț ia
9.în altă ordine de idei:

10. Litera 'W' nu a fost găsită în ș ir.

Asta este de obicei cum funcț ionează căutarea liniară; totuș i, putem avea mai mult
versiuni complicate la care vom ajunge în secț iunea următoare.

7.3 - Exemple
Notă importantă:

Dacă ai ceva experienț ă anterioară în programare, este posibil să fii


te întrebi de ce folosesc bucle while pentru a face asta? Fac asta în acest fel pentru
promova gândirea computaț ională ș i, în viitor, ne vom îndepărta de
această abordare.

În această secț iune, voi trece prin câteva exemple suplimentare de căutare liniară.
folosind bucle while, unele dintre ele pot deveni un pic complicate, aș a că petreceț i ceva
timp trecând prin ele.

Pentru primul nostru exemplu, să recreăm metoda de ș ir lstrip().

1.s = input()
2.
3.i = 0
[Link] i < len(s) ș i s[i] == " ":
5. i += 1
6.
7. dacă < len(s):
[Link](s[i:])
[Link]:
[Link]("Nu există caractere alfanumerice în acest ș ir")

62
Programul de mai sus va elimina toate caracterele de spaț iu alb de la început.

Să analizăm un exemplu mai dificil. Pentru această problemă, dorim ca utilizatorul să


introduceț i un ș ir ș i imprimaț i acel ș ir, eliminând toate spaț iile de la început ș i de la sfârș it

spaț iu alb ș i doar un caracter de spaț iu alb între fiecare cuvânt.


Introducere

Acesta este un ș ir

# IESIRE

Aceasta este un ș ir cu multe spaț ii albe

Acesta este greu de rezolvat ș i îmi amintesc că am primit această problemă când eu
învăț a să programeze. Pentru a rezolva această problemă, va trebui să utilizăm bucle while imbricate
în interiorul unul altuia.

1.s = input()
[Link] = ""
3.
4.i = 0
5.în timp ce i < len(s):
6. Găseș te un caracter non-spaț iu (începutul unui cuvânt)
7. în timp ce i < lungimea(s) ș i s[i] == " " :
8. i += 1
9.
10. j=i
11. dacă < len(s):
12. Găseș te sfârș itul acelui cuvânt
13. while j < len(s) and s[j] != " ":
14. j += 1
15.
16. Construieș te un ș ir din original fără spaț iile suplimentare.
17. output +=" "+ s[i:j]
18.
19. i=j+1
20.
21.
22.#Tipăriț i ș irul final
[Link](output[1:])

Nu o să explic asta, vreau să lucrezi la ea. Ia o simplă


ș ir de intrare pentru a te ajuta să parcurgi programul.

7.4 - Exerciț ii
Notă importantă:

Soluț iile pentru unele dintre aceste exerciț ii necesită gândire creativă.
Nu te aș tepta să ajungi la o soluț ie imediat!

63
Întrebarea 1
Write a program that takes a string from the user and prints the first number
întâmpinat împreună cu poziț ia sa.

Poț i presupune că numărul este o cifră unică


# EXAMPLE INPUT
Aceasta este capitolul 7 al cărț ii

# EXAMPLE OUTPUT
7 16

# EXAMPLE INPUT
Nu sunt cifre aici

#EXAMPLE OUTPUT

Niciun digit în ș ir

Întrebarea 2
Construind pe exerciț iul anterior, scrieț i un program care primeș te un ș ir ca
input de la utilizator ș i afiș ează primul număr întâlnit împreună cu
poziț ia de început a numărului.

Lucrul prin această întrebare pe hârtie ar fi o idee bună!


EXEMPLU DE TEXT
Acest capitol are 1208 cuvinte în el!

# EXEMPLO DE IEȘ IRE

1208 17

EXEMPLU DE ÎNTRARE

Nu există numere aici

64
# EXAMPLE OUTPUT
Niciun număr în ș ir

Întrebarea 3
Write a program that takes a string as input from the user. The string will
consta din cifre ș i programul tău ar trebui să imprime prima repdigit. A
Numărul repdigit este un număr în care toate cifrele sunt aceleaș i. Exemple de
numerele repetate sunt 22, 77, 2222, 99999, 444444. De asemenea, poț i presupune că fiecare
numărul va avea cifre diferite, cu excepț ia cazului în care este un repdigit.

# EXAMPLE INPUT
34 74 86 34576 47093 3 349852 777 9082

# EXEMPLU DE IEȘ IRE

777

# EXAMPLE INPUT
98 3462 245 87658

# EXEMPLE DE IEȘ IRE

Niciun repdigit în ș ir

Întrebarea 4
Dacă deschizi un browser ș i mergi pe orice pagină web care are text pe ea ș i apesi
Ctrl+f, o casetă de căutare va apărea. Poț i să scrii orice cuvânt în această casetă de căutare ș i
toate apariț iile acelui cuvânt de pe pagină sunt evidenț iate. Acest lucru nu foloseș te
linear search; it uses something called regular expressions (don't worry about
ce sunt). La fel ca apariț iile cuvântului fiind evidenț iate, tu
de asemenea, li se spune de câte ori apare cuvântul.

Trebuie să scrii un program care mimează acest comportament. Programul tău ar trebui să
ia un ș ir ca input de la utilizator ș i apoi un al doilea ș ir ca input care este
cuvântul pe care utilizatorul doreș te să-l caute. Programul tău ar trebui să imprime cum
de multe ori cuvântul apare în ș ir.

Presupuneț i că încă contează dacă cuvântul pe care îl căutaț i este încorporat în


un alt cuvânt, de exemplu, dacă utilizatorul căuta cuvântul "caută":

65
căutare ș i căutând <- poț i considera aceasta ca 2 apariț ii
# EXEMPLU DE INPUT
În acest tip de căutare, se face o căutare secvenț ială peste toate elementele unul câte unul.
unu
căutare

# EXEMPLE DE IEȘ IRE

# EXAMPLE INPUT
Nu va fi o întâmplare aici
python

# EXEMPLU DE IEȘ IRE

66
Capitolul 8 - Liste
Notă importantă:

Doar un avertisment, este mult de acoperit în acest capitol ș i poate deveni destul de
tehnic în anumite locuri (în special secț iunea 8.4) aș a că acordaț i o atenț ie deosebită acestuia
secț iune, este foarte important!

8.1 - Liste literale


Listele sunt, la prima vedere, cea mai simplă structură de date pe care Python o are de oferit. Ele
sunt de asemenea unul dintre cele mai importante ș i sunt folosite pentru a stoca elemente.

O listă este o secvenț ă de elemente în care elementele pot fi de orice tip


(numere întregi, numere zecimale, ș iruri de caractere, chiar ș i alte liste).

Listele sunt de tiplistă

Cel mai simplu tip de listă este lista goală ș i este reprezentată ca[]Gol
list isfalsey

>>>lista_gol=[]
>>>lista_vide==Fals
Adevărat
Într-o listă, elementele sunt separate prin virgule.

lista_mea=[1,2,3,654,7]
Această listă conț ine 5 elemente.

Putem amesteca tipurile din listă, de exemplu:

my_list=[True,88,3.14,"Hello", ['Another list',45938]]


Observaț i cum ultimul element este o altă listă

În Python, o listă este un tip de colecț ie, ceea ce înseamnă că poate conț ine mai multe obiecte.
(ș iruri, întregi, etc..) dar să fie tratate în continuare ca un singur obiect.

Listele sunt de asemenea un tip de secvenț ă, ceea ce înseamnă că fiecare obiect din colecț ie ocupă
o locaț ie numerotată specifică în interiorul său (ceea ce înseamnă că elementele sunt ordonate).

Listele sunt de asemenea iterabile, astfel încât putem itera prin elementele lor folosind indici.

Sunt foarte asemănătoare cu coardele, nu-i aș a?

67
Cu toate acestea, ele diferă în două moduri semnificative:

• O listă poate conț ine obiecte de tipuri diferite, în timp ce un ș ir poate doar
conț ine caractere
• O listă este un tip mutabil (Vom ajunge la asta mai târziu).

8.2 - Lista metodelor ș i funcț iilor


Putem obț ine lungimea unei liste în acelaș i mod în care facem cu ș irurile, folosind
thelen()funcț ie.

>>>my_list=[23,543,"hi"]
>>>len(my_list)
3
Avem de asemenea trei alte funcț ii destul de importante, acestea
suntsuma(), min()ș imax()ș i funcț ionează aș a cum te aș tepț i.

>>>my_list=[1,2,3,4,5,6]
>>>sum(lista_mea)
21
min()and max()de asemenea, lucrează cu ș iruri, deoarece ș irurile au un ordonare lexicografică
ordonare, 'a' fiind minimul ș i 'z' fiind maximum:

>>>my_list=[6,324,456,2,6574,-452]
>>>max(my_list)
6574
>>>min(lista_mea)
-452
>>>min("string")
'g'
>>>max("string")
't'
De asemenea, putem sorta o listă folosindordonat()funcț ie. Cesortat()funcț ia funcț ionează
prin conversia unei colecț ii într-o listă ș i returnarea listei sortate.

>>>student_grades=[88,23,56,75,34,23,84,63,52,77,96]
>>>sorted(student_grades)
[23,23,34,52,56,63,75,77,84,88,96]
În informatică, căutarea ș i sortarea sunt două probleme mari ș i sunt
subiecte importante.

Putem adăuga ș i elimina elemente de la sfârș itul unei liste. Adăugarea este a adăuga
and pop is remove. We can do this because lists aremutable.

>>>lista_mea=[1,5,8]
>>>my_list.append(99)
>>>lista_mea
[1,5,8,99]

68
>>>my_list.pop()
99
>>>lista_mea
[1,5,8]
>>>my_list.pop(2)
5
>>>lista_mea
[1,8]
Observaț i că atunci când eliminăm, ne este returnat numărul pe care l-am eliminat. Implicit,
dacă nu sunt trimise argumente laelimină()atunci ultimul element este eliminat. Putem
de asemenea, trimiteț i un index lapop()ș i va scoate elementul de la acel index
ș i returnaț i-l nouă.

Putem stoca valoarea care este returnată după apelareapop()într-o altă variabilă

>>>my_list=[1,5,9]
>>>x=my_list.pop()
>>>x
9
Dacă avem o listă de ș iruri sau caractere, le putem alătura folosind
thealătură-te()funcț ie:

>>>my_list=["O","r","a","n","g","e","s"]
"".join(my_list)
Portocale
Ș irul înainte de funcț ia de unire se numeș te ș ir de unire ș i este ceea ce va
fii între fiecare element al listei atunci când le alături. În acest caz
nu vrem nimic (ș irul gol).

Cu toate acestea, dacă am avea cuvinte, am putea dori să le unim împreună cu spaț ii:

>>>my_list=["Hello","World.","This","is","a","string."]
>>>' '.join(my_list)
Salut Lume. Aceasta este un ș ir.
Nota laterală:

Putem descompune un ș ir într-o listă folosindîmpărț iț i() function:

Aceasta este ș irul meu


>>>lista_mea=[Link]()
>>>lista_mea
["Aceasta","este","sirinia","mea"]
Theîmpărț iț i() funcț ia primeș te un argument care este caracterul pe care dorim să-l împărț im
ș irul activ. Dacă nu se trece niciun argument, atunci se împarte prin default la
spaț iu

69
8.3 - Indatarea listelor

Aș a cum am putea cu ș iruri, putem indexa ș i listele în acelaș i mod.

>>>my_list=[3,5.64,"Hello",True]
>>>lista_mea[2]
Bună
>>>lista_mea[0]
3
I've talked about how we can have other lists as elements inside lists. In
Python ș i multe alte limbaje, listele în interiorul listelor sunt utile pentru a reprezenta
multe tipuri de date (matrici, imagini, foi de calcul ș i chiar mai mult)
spaț ii dimensionale). Acestea sunt de obicei denumite multidimensionale
arrays sau liste multidimensionale.

Putem indexa ș i aceste liste interioare!

>>>my_list=[[1,2,3], [7,8,9]]
>>>lista_mea[0][1]
2
Acest lucru funcț ionează astfel, mai întâi selectăm lista încorporată dorită, apoi selectăm
elementul din acea listă. În exemplul de mai sus, vrem lista de la indexul 0
([1,2,3]) atunci selectăm elementul de la indexul 1 (2).

Putem să 'săpăm' în listele încorporate în acest mod.

>>>lista_mea=[[[1,2,3], [4,5,6]], [7,8,9]]


>>>lista_mea[0][1][1]
5
Putem extinde acest lucru la ș iruri în interiorul listelor

>>>my_list=["My string","Another string"]


>>>my_list[0][1]
y

8.4 - Referinț e ș i Mutabilitate


Am examinat tipurile imutabile mai devreme. Acum vom analiza tipurile mutable.
tipuri.

Un tip mutabil (sau o secvenț ă mutabilă) este unul care poate fi schimbat după ce a fost
creată. O listă este o secvenț ă mutabilă ș i, prin urmare, poate fi modificată pe loc.

Să ne reîmprospătăm memoria despre cum ș irurile nu puteau fi modificate după ce au fost


creat

s=" ș irul meu"

70
>>>s[0]="b"
Urmărirea erorilor (apelul cel mai recent a fost efectuat):
Fiș ier "<stdin>", linia 1, în <modul>
TypeError: obiectul 'str' nu faceatribui ț i elementul notsupport
Primeș ti o eroare. Aruncă o privire înapoi la capitolul despre ș iruri (Capitolul 6) ș i
revizuieș te diagrama care există în acel capitol.

O să introducestecuvânt cheie acum. Theestecuvânt cheie compară obiect


ID-uri (identităț i). Acest lucru este similar cu==care verifică dacă obiectele la care se face referire de către

variabilele au acelaș i conț inut (egalitate).

Pentru a face o analogie, să spunem că o companie de îmbrăcăminte produce în masă un anumit


tip de cămaș ă. Să luăm două cămăș i pe măsură ce ies de pe linie.

Am spuneshirt_1 == shirt_2 evaluează laAdevărat(Sunt amândouă la fel)


culoare, dimensiune ș i au aceeaș i grafică imprimată pe ele)

Am spunecămaș a_1 este cămaș a_2evaluează laFals(Deș i arată)


similar, nu sunt aceeaș i cămaș ă).

Mutenț a ș i imutabilitatea sunt destul de asemănătoare.

Să ne uităm la câteva exemple suplimentare de Python:

Bună
>>>t=s
tiss
Adevărat
>>>t==s
Adevărat
Aceste variabile,ssitse referă la acelaș i obiect (ș irul
"Bună". Ce ar fi dacă am încerca să actualizăm s?

Bună
>>>t=s
tiss
Adevărat
>>>s="World"
>>>t
Bună
Variabilasse referă acum la un alt obiect ș it încă referinț e
„Salut”. Deoarece ș irurile sunt imutabile, trebuie să creăm o nouă instanț ă. Nu putem
schimbă-l în loc.

Cu listele, însă, lucrurile funcț ionează puț in diferit.

>>>a=[1,3,7]
>>>b=a

71
poate
Adevărat
>>>[Link]ă(9)
>>>a
[1,3,7,9]
>>>b
[1,3,7,9]
>>>aisb
Adevărat
Comportamentul s-a schimbat aici ș i asta se datorează obiectului la care se face referire.
deaș ibismutable. Modificarea sa nu crează un nou obiect ș i
referinț a originală nu este suprascrisă pentru a indica un obiect nou. Noi nu
suprascrie referinț a din variabilăa, în schimb scriemprin aceasta pentru a modifica
obiectul mutabil la care face referire.

Cu toate acestea, există câteva trucuri mici adăugate în acest comportament. Luaț i în considerare
următorul cod:

>>>a=[1,3,7]
>>>b=a
>>>a=a+[9]
>>>a
[1,3,7,9]
>>>b
[1,3,7]
Ce se întâmplă aici? Asta contrazice ceea ce tocmai am discutat, nu-i aș a?
Ei bine, evident că nu, dezvoltatorii Python nu ar lăsa un bug atât de mare în
limbaj. Ce se întâmplă aici este că am executat următorul cod:a = a +
[9]. Aceasta nu scrie pentru a modifica lista la care se referă. În schimb, o nouă
lista este creată din concatenarea listeia ș i lista9.

O referinț ă la acest nou listă suprascrie referinț a originală îna. Lista


referinț at debeste astfel neschimbat.

Asta nu este tot, sunt ș i câteva trucuri ascunse. Există o subtilitate în plus. Consideră
următorul cod:

>>>a=[1,3,7]
>>>b=a
>>>a+=[9]
>>>a
[1,3,7,9]
>>>b
[1,3,7,9]
Se pare căx += ynu este întotdeauna prescurtare pentrux = x + yDeș i cu
tipuri imuabile fac acelaș i lucru, cu liste se comportă foarte
diferit. Se dovedeș te că+= operatorul aplicat pe liste, modifică

72
listă în loc. Asta înseamnă că scriem prin referinț ă înunș i
adăuga[9]la listă.

Scrierea prin referinț e este ilustrată mai jos.

În primul rând, consideraț i codul, apoi diagramă:

>>>a=[1,3]
>>>b=a
>>>a[1]=9

** ÎNAINTE DE A ACTUALIZA A **

LISTA NUMELOR LISTA OBIECT


=========== ===============
|-----| _____
_____ | | 1
a | # |------------------>| # |--------->|---|
|---| | | _____
_____ | # |--------->| 3 |
b | # |------------------>|_____| |---|
|---|

** DUPĂ ACTUALIZAREA A **

LISTA DE NUME LISTA OBIECT


=========== ===============
|-----| _____
_____ | | |1|
a | # | ----------------->| # |---------> |---|
|---| | | _____
_____ | # |-----| 3
b | # | ----------------->|_____| | |---|
|---| |
| |---|
|---> | 9 |
|---|
Ce se întâmplă în a doua parte a acestui diagram?#'s reprezintă
referinț e.

uneste o referinț ă la un obiect de tip listă care conț ine referinț e la întregi.

breferinț ele la acelaș i obiect listă. Dar când "schimbăm"a, nu suntem clar
schimbându-l. Actualizăm o referinț ă în cadrul acestuia. În timp cebdoar puncte către
listăas-a schimbat ceea ce este în interiorul său, prin urmareb's reference nu este afectată.

We can still see the 3 plutind în a doua parte a diagramei. Aceasta


va fi preluat de ceva numit colectorul de gunoi (un gunoi

73
colectorul menț ine memoria curată ș i o opreș te să devină inundată cu lucruri
like the unreferenced 3).

Este important să păstrezi o imagine mentală a acestui lucru.

8.5 - Operaț ii cu liste


Am văzut două operaț iuni (Acum ș tiind că sunt diferite) în precedent
secț iunea. The+ ș i+=operatori. Voi trece rapid peste ei din nou.

[1,2,3]
> b = [4, 5, 6]
>>>a+b
[1,2,3,4,5,6]
>>>a+=b
>>>a
[1,2,3,4,5,6]
De asemenea, avem ș i* operator, care face ceea ce se aș teaptă:

>>>a=[1,2,3]
>>>a*3
[1,2,3,1,2,3,1,2,3]
Avem ș i un nou operator. Acesta esteînoperator. Theînoperatorul este
un operator de testare a apartenenț ei ș i returneazăAdevăratdacă o secvenț ă are o specificare
valoarea se află într-un obiect

>>>a=[3,7,22]
>>>4ina
Fals
>>>3ina
Adevărat
Theînoperatorul poate fi aplicat oricărui tip iterabil (liste, ș iruri, etc).

8.6 - Felierea listelor

Împărț irea listelor funcț ionează exact aș a cum o face cu ș irurile de caractere. Acest lucru are sens deoarece ambele

ș iruri ș i liste sunt tipuri de secvenț e.

[1,2,3,"Salut",Adevărat]
>>>a[3:]
["Hello",True]
>>>a[-4:-2]
[2,3]
Slicing-ul extins funcț ionează exact la fel ca ș i cu ș irurile.

a=[1,2,3,"Bună",Adevărat]
>>>a[::-1]
[True,'Hello',3,2,1]

74
>>>a[::2]
[1,3,Adevărat]
Important:

Aminteș te-ț i că în secț iunea 8.4 am scris ceva de genul:

>>>a=[1,2,3]
>>>b=a
Dacă am actualizata, apoibar fi afectată. Ce ar fi dacă am dori să facem o
copie deaș i păstrează-l înb? Putem folosi tăierea pentru a face asta, deoarece tăierea returnează un
obiect nou

>>>a=[1,2,3]
>b=a[:]
bisa
Fals
Putem vedea acum că ele nu se referă la acelaș i obiect, aș a că actualizarea unuia va
nu afecta cealaltă.

8.7 - Exerciț ii
Notă importantă: Am învăț at multe până în acest punct. Soluț iile dumneavoastră ar trebui să
combinând (acolo unde este necesar) tot ce am învăț at până acum. Dacă eș ti
dacă nu eș ti sigur de ceva, nu te teme să te întorci la capitolele anterioare. E
este complet normal să nu îț i aminteș ti totul atât de devreme. Cu cât mai mult
practica, cu atât mai mult din aceste lucruri se va lipi!

Întrebarea 1
Scrie un program care ia un ș ir ca intrare de la utilizator, urmat de un
number and output each word which has a length greater than or equal to the
număr.

Ș irul va fi o serie de cuvinte precum"apple orange pear grape melon


lămâie

Trebuie să foloseș tiîmpărț iț i() funcț ie pentru a împărț i ș irul

EXEMPLU DE INPUT
elefant pisică câine ș oarece urs lup leu cal
5

# EXEMPLE DE IEȘ IRE


elefant
mouse

75
cal
Puteț i folosi următorul cod la începutul programului dvs.

cuvintele_mele=input().split()
num=int(input())

# CODUL TĂU AICI


# AMINTEȘ TE: my_words este o listă

Întrebarea 2
Scrieț i un program care acceptă un ș ir ca intrare de la utilizator, urmat de
o altă sfoară (sufixul) ș i ieș i fiecare cuvânt care se termină cu sufixul.

Prima ș ir va fi o serie de cuvinte cum ar fimere portocale pere struguri


lămâi pepeni

Trebuie să foloseș tiîmpărț i() funcț ie pentru a împărț i ș irul

# EXAMPLE INPUT
mere portocale pere struguri lămâi pepeni
es

# EXEMPLU DE IEȘ IRE


mere
portocale
struguri
Sugestie: Soluț ia ta ar trebui să fie generalizată pentru orice sufix. Nu presupune că
lungimea sufixului va fi 2

Puteț i folosi următorul cod la începutul programului dumneavoastră.

cuvinte=input().split()
suffix=input()

# CODUL TĂU AICI


# AMINTEȘ TE: cuvintele sunt o listă

Întrebare 3
Scrieț i un program care construieș te o listă de întregi din input-ul utilizatorului. Ar trebui să vă opriț i

când utilizatorul introduc0.

Programul tău ar trebui să imprime lista.

# EXAMPLES INPUT
3
5
6
7
0

# EXAMPLE OUTPUT

76
[3, 5, 6, 7]
Întrebarea 4
Folosind soluț ia ta la întrebarea 3, luând o listă construită din inputul utilizatorului,
întreabă utilizatorul pentru două bucăț i suplimentare de input. Întregi de data aceasta.

Numerele întregi vor reprezenta indicii. Trebuie să schimbi elementele la


indici specificaț i între ei.

# EXAMPLE INPUT
6
3
9
0

*********************************
* LISTA AR TREBUI SĂ FIE ÎN PREZENT: [6, 3, 9] *
*********************************

1
2

# EXEMPLU DE IEȘ IRE


[6, 9, 3]
Puteț i presupune că indicii vor fi în intervalul de indici al listei.

Întrebarea 5
Scrie un program care construieș te o listă de întregi din inputul utilizatorului. Programul tău
ar trebui apoi să găsească cel mai mic dintre aceste numere întregi ș i să-l pună la primul index (0)
în listă. Inputul se termină când utilizatorul introduce 0.

# EXAMPLE INPUT
10
87
11
5
65
342
12
0

# LISTA AR TREBUI SĂ FIE ACUM: [10, 87, 11, 5, 65, 342, 12]

# EXAMPLE OUTPUT
[5, 87, 11, 10, 65, 342, 12]
Această problemă este puț in mai greu de rezolvat, gândeș te-te la soluț ia ta!

77
Întrebarea 6
** ACESTA ESTE O PROBLEMĂ DIFICILĂ **

Scrie un program care ia două liste sortate ca input de la utilizator ș i le îmbină.


împreună. Lista rezultată ar trebui să fie de asemenea sortată. Ambele liste de intrare
va fi în ordine numerică crescătoare, lista rezultată ar trebui să fie de asemenea.

# EXEMPLU DE INTRODUCERE

2
6
34
90
0 # SFÂRȘ ITUL PRIMULUI INPUT
5
34
34
77
98
0 # SFÂRȘ ITUL AL DOILEA INPUT

# EXAMPLE OUTPUT
[2, 5, 6, 34, 34, 34, 77, 90, 98]
Nu presupune că ambele liste vor avea aceeaș i lungime!

78
Capitolul 9 - Algoritmi de sortare de bază
9.1 - Ce este sortarea?
Am învăț at multe până acum ș i acum este timpul să punem în aplicare ceea ce am învăț at.
foloseș te. Acum vom analiza primele tale algoritmi importanț i.
Sortarea este procesul de aranjare sistematică a elementelor. În ș tiinț a calculatoarelor,
sortarea se referă la aranjarea articolelor (indiferent ce ar fi acestea) într-o ordine
secvenț ă.

Sortarea este o operaț iune foarte comună în aplicaț ii ș i


dezvoltarea de algoritmi eficienț i pentru a efectua sortarea devine din ce în ce mai
sarcină importantă, deoarece cantitatea de date pe care o colectăm creș te într-un ritm exponenț ial.

Sortarea este de obicei folosită pentru a susț ine eficienț a căutării sau a căutării, pentru a permite
procesarea datelor într-o ordine definită posibilă ș i pentru a realiza fuziunea de
secvenț e eficiente.

În acest capitol vom analiza două dintre aceste algoritmi de sortare:


Sortare prin selecț ie ș i Sortare prin inserț ie.

9.2 - Sortare prin selecț ie

Sortarea prin selecț ie este un algoritm de sortare de uz general. Pentru ca sortarea prin selecț ie
pentru a lucra trebuie să presupunem că există o anumită secvenț ă de elemente care sunt
comandabil (întregi, zecimale, etc.).
Sortarea prin selecț ie este un algoritm de sortare in-place, ceea ce înseamnă că nu construim un
listă nouă, mai degrabă, reorganizăm elementele acelei liste.

Înainte de a începe, trebuie să ne uităm la câteva terminologii:

• Subarray sortat - Porț iunea din listă care a fost sortată


• Subarray nesortat - Porț iunea listei care nu a fost încă sortată
• o- Lista pe care o sortăm

În sortarea prin selecț ie, împărț im lista în două părț i, subarray-ul sortat ș i
subarray nesortat ș i toate elementele din subarray sortat sunt mai mici decât
sau egal cu toate elementele din subarray-ul nesortat. De asemenea, începem cu
presupunerea că întreaga listă este nesortată.

79
Apoi, căutăm în întreaga listă poziț ia celui mai mic element. Noi
trebuie să căutăm întreaga listă pentru a ne asigura că am găsit cel mai mic
element. Dacă există multiple apariț ii ale celui mai mic element, luăm
poziț ia primului. Apoi, mutăm acel element în poziț ia corectă
a subarray-ului sortat. Repetăm paș ii de mai sus pe subarray-ul nesortat
Acest lucru este ilustrat mai jos

6 3 9 7 2 8
|||========================| GĂSEȘ TE POZIȚ IA CEA MAI MICĂ
PARTE NESORTATĂ ELEMENT ÎN LISTĂ Ș I SCHIMBAȚ I CU
6

--------------------------------------------------------------------------
--

2 3 9 7 6 8 # 2 ESTE ACUM ÎN POZIȚ IA CORECTĂ


|===||===================| GĂSEȘ TE POZIȚ IA CEA MAI MICĂ
PARTE NESORTATĂ # ELEMENT ÎN LISTĂ Ș I SCHIMB CU
3
3 ESTE CEL MAI MIC (FĂRĂ SCHIMBARE)

--------------------------------------------------------------------------
--

2 3 9 7 6 8 # 3 ESTE ACUM ÎN POZIȚ IA CORECTĂ


|========||==============| # GĂSEȘ TE POZIȚ IA CEA MAI MICĂ
PARTE SORTATĂ NESORTATĂ # ELEMENT ÎN LISTĂ Ș I SCHIMB CU
9
PARTE

--------------------------------------------------------------------------
--

2 3 6 7 9 8 # 6 ESTE ACUM ÎN POZIȚ IA CORECTĂ


|=============||=========| Cautaț i poziț ia celui mai mic

80
PARTE SORTATĂ NEORDERAT # ELEMENT ÎN LISTĂ Ș I ÎNLOCUIȚ I CU
7
PARTE 7 ESTE CEL MAI MIC (FĂRĂ SCHIMBARE)

--------------------------------------------------------------------------
--

2 3 6 7 9 8 7 ESTE ACUM ÎN POZIȚ IA CORECTĂ


|==================||=====| GĂSEȘ TE POZIȚ IA CELUI MAI MIC
PARTE SORTATĂ NENUMĂRAT # ELEMENT DIN LISTĂ Ș I SCHIMBAȚ I CU
9

--------------------------------------------------------------------------
--

2 3 6 7 8 9 # 8 ESTE ACUM ÎN POZIȚ IA CORECTĂ


|========================||| AM AJUNS LA SFÂRȘ ITUL
LISTĂ

PARTE SORTATĂ LISTA ESTE ACUM SORTATĂ

Pare oarecum familiar? Dacă ai făcut exerciț iile dinainte


capitolul, exerciț iul 5 a fost practic acest proces!

Este timpul să codificăm sortarea prin selecț ie! Să ne uităm la codul pentru aceasta mai jos:

1.i = 0
2.în timp ce i < len(a):
3. p=i
4. j=i+1
5. whilej < len(a):
6. ifa[j] < a[p]:
7. p=j
8. j += 1
9.
10. tmp = a[p]
11. a[p] = a[i]
12. a[i] = tmp
13.
14. i += 1

Asta e! Să descompunem asta, deoarece se întâmplă multe aici

• Bucle extern controlerează subarray-ul nostru sortat.


• Bucla interioară while caută următorul cel mai mic element

81
• Cele trei linii de mai susi += 1schimbă elementul cel mai mic în
poziț ie corectă.
• Procesul se repetă apoi.

O abilitate pe care toț i programatorii o au este capacitatea de a parcurge codul ș i


află cum funcț ionează. Te încurajez să faci la fel cu asta
algoritm (creion ș i hârtie ș i parcurgerea unui exemplu)

O altă modalitate bună de a înț elege ce se întâmplă în mijlocul unui cod este să
lipiț i într-unprint()declaraț ie pentru a tipări ce valori deț in ce variabile la
acel timp curent. O altă modalitate bună este să setez puncte de întrerupere. Nu voi
îț i arăt cum să faci asta, deoarece este în general o caracteristică a editorului de text pe care îl foloseș ti

foloseș te aș a că caută cum să setezi puncte de întrerupere pentru editorul tău ș i cum să le foloseș ti!

Este o abilitate pe care te-ai aș tepta să o ai dacă ai lucra în acest domeniu.

9.3 - Sortare prin inserț ie

Sortarea prin inserț ie este un alt algoritm de sortare de uz general, care se face în loc.

Pentru a contrasta modul în care funcț ionează sortarea prin inserț ie comparativ cu sortarea prin selecț ie:

• Sortare prin selecț ie: Selectaț i cel mai mic element din subarray-ul nesortat
ș i îl adaugă la subarray-ul sortat al listei.
• Sortare prin inserț ie: Ia următorul element din subarray-ul nesortat ș i inserează-l
în poziț ia sa corectă în subarray-ul sortat.

Voi ilustra acest lucru cu un exemplu semi-complet:


2 4 5 3 96
|=============||==========| STAREA LISTEI LA UN MOMENT DAT
SORTED UNSORTED # ÎN TIMPUL PROCESEI DE SORTARE CU INSERȚ IE

-----------------------------------------------------------------------

Acesta este următorul element pe care vrem să-l sortăm

|
|
2 4 5 3 96
|=============||==========| VREM SĂ PLASĂM ACUM 3 ÎN EL

82
SORTAT NEORDONAT # POZIȚ IE CORECTĂ

-----------------------------------------------------------------------
3
2 4 5 _ 96
|=============||==========| Scoate 3 din listă
SORTED UNSORTED

-----------------------------------------------------------------------

3
2 4 5 _ 96
|=============||==========| Este 3 < 5? DA, AȘ A CĂ MUTĂ 5 ÎN SUS

SORTED UNSORTED

-----------------------------------------------------------------------

3
2 4 _ 5 96
|=============||==========| # ESTE 3 < 4? DA, AȘ A CĂ MUTĂ 4 ÎN SUS

SORTED UNSORTED

-----------------------------------------------------------------------

3
2 _ 4 5 96
|=============||==========| # ESTE 3 < 2? NU, PLASEAZĂ DUPĂ 2
SORTED UNSORTED

-----------------------------------------------------------------------

83
2 3 4 5 96
|=============||==========| # 3 SE AFLĂ ACUM ÎN POZIȚ IA CORECTĂ
SORTAT NEORDONAT

-----------------------------------------------------------------------

2 3 4 5 96
|==================||=====| TRECE LA URMĂTORUL ELEMENT
SORTED UNSORTED

Este timpul să codăm sortarea prin inserț ie! Să aruncăm o privire asupra codului pentru aceasta, voi da
explicaț ie ca comentarii:

1.i = 1 # Presupune că primul element (a[0]) este sortat


2.în timp ce i < len(a): # La fel ca la sortarea prin selec ț ie
3. v = a[i] Valoarea pe care dorim să o introducem în poziț ia corectă
4. p=i Poziț ia în care elementul ar trebui să fie inserat în
5. în timp ce p > 0 ș i v < a[p-1]:În timp ce valoarea este < elementul din stânga
6. a[p] = a[p-1] Mută elementul în sus la stânga
7. p -= 1 Decrementează p (măreș te o poziț ie la stânga)
8. a[p] = v Am găsit poziț ia corectă, aș a că introduc valoarea
9.
10. i += 1 Mutaț i la elementul următor

9.4 - Compararea sortării prin selecț ie ș i sortării prin inserț ie

În această secț iune o să vorbesc despre complexitatea algoritmică a celor două


algoritmi. Aceasta este o secț iune foarte importantă. Dacă vreodată faci un tehnic
în 99.9% din cazuri, ț i se va cere să scrii un cod sau un algoritm
ș i dă-i complexitatea algoritmică. Trebuie să ș tii aceste lucruri ș i nu este
doar pentru Python, acest lucru se aplică oricărei limbi! O să explic acest lucru în
calea cea mai simplă posibilă, oferindu-vă în continuare o bună înț elegere a subiectului.

Sortarea prin selecț ie ș i sortarea prin inserare sunt ceea ce numim algoritmi de sortare pătratică.

84
Aceasta înseamnă că ambele au o complexitate de timp O mare de:
O(n)2
Complexitatea temporală se referă la timpul necesar pentru ca algoritmul să se finalizeze.
Există în general trei categorii:

• Cel mai bun caz - De exemplu, cu sortarea prin inserț ie, să zicem că lista noastră este
already sorted and we try to sort it, then we are in a best case scenario
deoarece nu trebuie să mutăm niciun element ș i algoritmul
se termină repede.
• Cazul mediu: Acesta este modul în care algoritmul se comportă în termeni de timp pe
medie
• Cea mai proastă situaț ie: Aș a ar performa algoritmul în termeni
dacă lista noastră ar fi fost complet amestecată ș i dezordonată.

Big O se ocupă cu cazul cel mai rău ș i acesta este cazul cu care ne preocupăm de obicei
cu!
Există multă matematică în spatele acestui lucru ș i există un întreg subiect de informatică.

ș tiinț a legată de aceasta, aș a că nu o discut în detaliu aici.

Oricum, când spunem că ambele aceste algoritmi au o complexitate temporală


de O(n^2), spunem esenț ial că performanț a algoritmilor
va creș te proporț ional cu pătratul dimensiunii intrării (liste în acest
Un alt mod de a ne gândi la O(n^2) este că, dacă dublăm dimensiunea inputului nostru,
va quadrupla timpul necesar pentru ca algoritmul să se finalizeze. Acestea sunt doar
estimări. Nu înseamnă că două algoritmi cu complexităț i temporale
O(n^2) vor dura exact la fel de mult timp pentru a se finaliza. Puteț i privi aceasta
ca un ghid referitor la modul în care algoritmul tău va funcț iona într-un sens general.

Am luat timpul să rulez câteva algoritme cu diferite complexe de timp pe


liste de dimensiuni variate ș i putem observa cum algoritmul durează mai mult pentru
completat pe măsură ce dimensiunea listei creș te. Puteț i vedea acest lucru în diagrama de mai jos:

85
Complexitatea timpului

În acest diagramă, axa y reprezintă cât de mult a durat algoritmul pentru a termina
în secunde ș i axa x arată numărul de elemente din listă.
Linia albastră este pentru un algoritm O(n^2) iar cea portocalie este pentru un O(n)
algoritm (algoritm de timp liniar).

Am un computer rapid, aș a că nu pare că linia portocalie se schimbă (ea


este, doar foarte încet).

Cu toate acestea, este foarte clar că algoritmii O(n^2) devin foarte lent atunci când
dimensiunea intrării devine mare.
În lumea reală, o listă de dimensiune 1000 este mică ș i sortarea prin selecț ie sau sortarea prin inserț ie
nu ar funcț iona. Cu toate acestea, acest lucru nu înseamnă că nu au utilizările lor. De fapt,
în practică, sortarea prin selecț ie ș i sortarea prin inserț ie depăș esc algoritmii mai rapizi
pe liste mici ș i unele dintre algoritmii de sortare rapidi vor comuta de fapt la
aceș ti algoritmi O(n^2) când se apropie de sfârș itul procesului de sortare.
Se pare că întregul proces se finalizează mai repede când acest lucru este făcut (în unele cazuri).

Avem de asemenea ceva numit complexitatea spaț ială ș i aceasta se referă la modul în care
o mare memorie este ocupată de un algoritm. Ambele algoritmi au O(1)
complexitate spaț ială. Aceasta înseamnă că folosesc memorie constantă. Folosesc constant
memorie, deoarece sunt algoritmi de sortare in-place. Nu creează suplimentar
liste pentru a asista în procesul de sortare.

86
De obicei există un compromis între complexitatea temporală ș i complexitatea spaț ială. Aș a cum poț i

vezi aici, avem memorie constantă (Asta este bine) dar timp quadratic
complexitate (aceasta este rea). Am putea scrie un algoritm care este mai rapid, dar necesită
mai multă memorie. Depinde de problemă ș i de resursele de calcul pe care le avem.
a avea.

9.5 - Exerciț ii
Nu vor fi exerciț ii de programare în acest capitol, doar întrebări teoretice.
Sunt la fel de importante de înț eles ș i de făcut corect!

Întrebare 1
Care este complexitatea temporală a:

Sortare prin inser ț ie


2. Sortare prin selec ț ie

Oferă-ț i răspunsul în notaț ia Big O

Întrebarea 2
Care este complexitatea spaț ială a:

1. Sortare prin selec ț ie


2. Sortare prin inser ț ie

Oferiț i-vă răspunsul în notaț ie Big O

Întrebare 3
Oferiț i două exemple de când am putea folosi sortarea prin selecț ie sau sortarea prin inserț ie în
lumea reală?

Întrebare 4
Dacă ne-am pomeni într-o situaț ie în care inputul era sortat, dar noi nu ș tiam
ș i încercăm să sortăm inputul, de ce am putea prefera sortarea prin inserț ie în locul celei prin selecț ie

sorta?
S-ar putea să trebuiască să mergi ș i să cauț i răspunsul la aceasta.

87
Procesarea inputului, fiș ierelor ș i textului

10.1 - Ce este procesarea fiș ierelor ș i textului?

Procesarea fiș ierelor este procesul de creare, stocare ș i accesare a conț inutului unui fiș ier.
Până acum, am reuș it să stocăm datele temporar în programele noastre.
în obiecte precum liste. În lumea reală, aceasta nu ar fi de mare ajutor. Avem nevoie de
o modalitate de a putea salva date permanent. Pentru a face acest lucru, programele noastre
trebuie să stochezi date pe un hard disk. Acesta este un mediu de stocare persistent ș i datele din
această stocare va putea supravieț ui unei reporniri a sistemului sau unui crash al programului nostru. Dacă

rebootăm sistemul nostru, RAM-ul este ș ters ș i pierdem datele noastre. Am fost
stocarea datelor în RAM până acum.

Când facem procesarea fiș ierelor, urmăm aceș ti paș i:

• Deschide fiș ierul


• Citeș te ș i/sau scrie în fiș ier
• Închide fiș ierul

Până acum am folositintroduceț i() ș iprint()pentru intrare ș i ieș ire (I/O).


Acestea sunt interfeț e de nivel înalt pentru serviciile de sistem de operare subiacente
ș i uneori avem nevoie de un control mai fin, mai ales atunci când vrem să citim ș i
write files.
Python implementează obiecte de fiș ier ca interfeț e generale pentru fluxurile de date. Aceste fiș iere
obiectele ne permit să citim ș i să scriem de la ș i în standardul de intrare ș i standardul
output (asta este ceinput()ș iprint()facem ș i vom ajunge la intrarea standard ș i
fiș ierele obiecte ne permit de asemenea să citim ș i să scriem fiș iere.

Pe de altă parte, prelucrarea textului este procesul de manipulare a textului


date. Procesarea textului este o sarcină foarte comună în informatică. Python are multe
sprijin pentru procesarea textului ș i am întâlnit chiar câteva dintre metodele care
Python oferă posibilitatea de a face asta. Acestea
suntîmpărț iț i(), ș terge() ș ialăturare()a numi câteva.

10.2 - Modulul Sys


Modulul sys oferă informaț ii despre constante, funcț ii ș i metode
al interpretului Python. Un modul este un fiș ier care constă din cod Python. Un

88
modulul poate defini funcț ii, clase ș i variabile. Pentru a accesa un modul trebuie să
trebuie să-l importaț i în codul dvs. folosindimportacuvânt cheie.
importaț i sistem

# CODUL TĂU

Prin intermediul modulului sys putem accesa argumentele care sunt transmise către noi
script la linia de comandă. Multe scripturi Python necesită acces la acestea
argumente. Avem acces la ele prinargv([Link]).
argveste o prescurtare pentru vectorul de argumente. Aceasta este o listă care conț ine comanda-
argumentele liniei transmise scriptului. Primul element din această listă este scriptul
însuș i. Argumentele pentru script vin după numele scriptului. Să
uită-te cum funcț ionează asta. Creează un nou fiș ier Python ș i salvează-l ca [Link] ș i
introduceț i următorul cod:
importaț i sistemul

print([Link])

Apoi, la linia de comandă, tastează următoarele, apoi Enter:


1$ py [Link] arg1 arg2

Dacă eș ti pe Linux sau macOS, tastează:python3 [Link] arg1 arg2

The$ la început este promptul de comandă, nu tastaț i asta.

Vei obț ine următorul rezultat:


$ py [Link] arg1 arg2
["[Link]","arg1","arg2"]

Să folosim acest lucru într-un mod mai constructiv. Creează un fiș ier nou
numit [Link] ș i lipiț i următorul cod:

[Link]
2.
[Link] = 0
4.
5.i = 1
6.în timp ce i < len([Link]):
7. total += int([Link][i])
8. i += 1
[Link](total)

89
În linia de comandă, tastează următoarele, apoi apasă Enter:

$ py [Link] 5 3 6
14

Putem trece numerele pe care dorim să le adunăm în script. Acest lucru ne economiseș te
a fi nevoit să cerem utilizatorului input de fiecare dată când dorim o nouă introducere. Amintiț i-vă

totuș i, argv este o listă de ș iruri de caractere ș i de aceea a trebuit să convertim argumentele la
numere întregi în codul de mai sus.

Thesistemmodulul ne ofer, de asemenea, trei obiecte standard de fiș iere. Acestea


sunt:stdin, stdout, si stderr. Acestea reprezintă intrarea standard, standard
ieș ire ș i eroare standard.

În secț iunile care urmează, vom analiza fiecare dintre ele.

10.3 - Citirea din intrarea standard


Intrarea standard este un flux de date (de obicei text) care intră într-un program. În Python,
accesăm intrarea standard prin intermediul modulului sys care oferă standard
introducere (stdin) ca un obiect de fiș ier.

Avem diverse metode disponibile pentru a citi din standard.


input.

Important: Următoarele metode, spre deosebire deîntroduceț i() ș iprint(), nu voi adăuga niciodată
sau eliminaț i caracterele de linie. Va trebui să gestionăm caracterele de linie
noi înș ine.

Primul esteciteș te()metodă. Este cea mai de bază dintre cele [Link]ș te() va citi
întreaga conț inuturi a fiș ierului ș i întregul conț inut va fi atribuit unui
string singular.
12345importaț i sistemul

conț inuturi= [Link]()

printaț i(conț inutul)

Important: Putem trece un fiș ier programului nostru folosind un operator de linie de comandă
numit operatorul de redirecț ionare a intrării. Când folosim acest operator, redirecț ionăm
input de la tastatură în fiș ierul text.

90
Sintaxa pentru această metodă [Link]()[Link] un fiș ier (obiect fiș ier)
aici).

Ar trebui să creezi un fiș ier text ș i să-l umpli cu câteva texte. Îț i recomand să
have about 10 lines of text. Each line can be a single word if you like.
Pentru a rula codul de mai sus, tastaț i următoarele în linia de comandă. Asiguraț i-vă că
fiș ierul de text ș i scriptul Python sunt în acelaș i director. Tastaț i următoarele,
apoi Apasă Enter.

$ py [Link] < [Link]


Acesta este linia unu.

Sunt pe linia doi

Ș i eu sunt pe linia trei

Aceasta funcț ionează la fel pe Linux, Windows ș i Mac.

Aceasta este ieș irea pe care o obț inem. A ta va arăta diferit în funcț ie de ceea ce
aveț i în fiș ierul dvs. Aș a cum puteț i vedea, am imprimat acel fiș ier pe care tocmai l-aț i creat.

Citeș te fiș ierul ca un singur ș ir ș i ș irul arată astfel:


Aceasta este linia unu. Sunt linia doi Ș i sunt linia trei

A doua metodă pe care o avem la dispoziț ie esteciteș te liniile()metodă. Aceasta este


puț in mai complicat, deoarece stochează fiecare linie ca un element într-o listă.

[Link]
2.
[Link] = [Link]()
4.
[Link] ț i(conț inuturile)

Sintaxa pentru această metodă [Link]()[Link] un fiș ier (fiș ier


obiect aici).

Acum rulăm scriptul nostru la fel ca înainte:


$ py [Link] < [Link]
['This is line one.\n', "I'm line two.\n", "And I'm line three"]

După cum puteț i vedea, fiș ierul nostru text este acum stocat într-o listă, fiecare linie fiind un
element în listă. Observaț i cum caracterele de newline nu au fost eliminate.
Această metodă este bună, deoarece acum putem face unele manipulări pe fiecare linie de text
mai uș or.

91
În loc să folosim operatorul de redirecț ionare a intrării, putem citi pur ș i simplu liniile din
terminal.
Puteț i rula din nou scriptul de mai sus, de data aceasta omiț ând operatorul de redirecț ionare.

Important: Cu fiș ierele ajungem în cele din urmă la sfârș itul acestora. Acest lucru este indicat în
fiș ierul prin EOF (final de fiș ier). Nu trebuie să ne facem griji cum funcț ionează asta, deoarece
este gestionat la un nivel mai scăzut. Când nu redirectăm intrarea standard pentru a citi
dintr-un fiș ier, trebuie totuș i să indicăm EOF la linia de comandă. Pe
În Windows, acest lucru se face apăsând ctrl+z. Pe Linux, acest lucru este indicat prin apăsarea
ctrl+d. Când rulezi din nou scriptul de mai sus ș i omiti redirecț ionarea, vei fi
Îndemnat să introduci continuu linii de text. Când ai terminat, apasă
ctrl+z sau ctrl+d.
$ py [Link]
linie unul
linie doi
linie finală # APĂSAȚ I ENTER, Apoi CTRL+Z SAU CTRL+D PENTRU A INDICA EOF.

["linie una\n","linie doi\n","linie finală\n"]

A treia metodă disponibilă pentru noi estecitire()metodă. Aceasta este discutabil


mai bine decâtciteș te() ș ireadlines()deoarece citeș te doar o singură linie din standard
Cu cele două metode anterioare, am putea imagina o situaț ie în care o
fiș ierul de text este cu adevărat, cu adevărat mare ș i stocarea întregului conț inut al fiș ierului în
memoria ar putea fi o risipă de memorie valoroasă.

Putem citi încă multe linii de input folosind această metodă, va trebui doar să avem nevoie de o
ciclul. Să vedem cum se face asta.

[Link]
2.
[Link] = [Link]()
[Link]:
5. print([Link]()) # Elimină caracterul de linie nouă deoarece print() va adăuga unul.

6. linie = [Link]()

Sintaxa pentru această metodă [Link]()[Link] un fiș ier (fiș ier


obiect aici).
Rularea acestuia în timp ce redirecț ionaț i intrarea standard către un fiș ier produce:

$ py [Link] < [Link]


Aceasta este linia unu.

92
Sunt pe linia doi.

Ș i eu sunt pe linia trei

Vreau să arunc o altă privire laciteș te()metodă. Putem de fapt controla cum
mare parte din input este citit. Dacă redirecț ionăm inputul către un fiș ier, putem limita cât de mult
al fiș ierului pe care îl citim în orice moment dat. În mod similar, dacă nu redirecț ionăm, putem limita
cât de mult din inputul utilizatorului prin consolă citim. Facem asta prin transmiterea
un întreg ca argument al metodei. Acest întreg reprezintă câte
caractere pe care vrem să le citim.

Aceasta se face astfel:

[Link]
2.
[Link] = [Link](6)
4.
[Link]ă(con ț inuturile)

Rularea codului ș i redirecț ionarea intrării standard către un fiș ier text ar produce:

$ py [Link] < [Link]


Acesta este

Aș a cum poț i vedea, am trecut integerul 6 funcț iei de citire, spunându-i să doară
citeș te 6 caractere.
Aminteș te-ț i: Spaț iul gol contează ca un caracter ș i la fel ș i newline-ul.
personaj!

Obiș nuieș te-te cu aceste metode! Aș a vom fi principala modalitate de a lua


introduceț i în funcț iile noastre de acum înainte!

10.4 - Scrierea în ieș irea standard


Ieș irea standard se referă la fluxurile de date care sunt generate de programe.
Aceste fluxuri standardizate fac foarte uș or să trimiteț i ieș irea de la acestea
programe pentru monitorul de display al unui dispozitiv, imprimantă, etc.

Scriem pe ieș irea standard folosindscrie()metodă pe


[Link] de fiș ier. Comportamentul luiscrie()s-a schimbat de când Python
2.x. În Python 3, când scriem în ieș irea standard, primim înapoi
numărul de caractere care au fost scrise.

93
Să vedem asta în acț iune în REPL-ul Python:
>>>importsys
>>> [Link]("Salut")
Bună5

>>>

Putem observa că am scris "Salut" pe ieș irea standard ș i am primit înapoi


numărul de caractere care au fost scrise5). Motivul pentru care 5este pe aceeaș i
linia este pentru că, spre deosebire deprint(), trebuie să adăugăm caracterul de linie nouă
ourselves:
>>>importsistem
>>> [Link]("Salut\n")
Bună
5
>>>

De asemenea, putem redirecț iona fluxul standard de ieș ire către un fiș ier folosind ieș irea
operator de redirecț ionare>). Haideț i să vedem cum se face asta.

[Link]
2.
[Link]("Salut Lume! ")

Apoi, în linia de comandă, rulează:

1$ py [Link] > [Link]

Dacă verifici directorul în care este stocat scriptul tău, ar trebui să vezi acum un
fiș ier numit [Link].
Deschide-l ș i vizualizează conț inutul său, ar trebui să conț ină ceea ce tocmai am scris în
flux de ieș ire.
Când redirecț ionăm ieș irea standard către un fiș ier, un fiș ier va fi creat dacă nu există.
există deja.
Avem de asemenea ș iwritelines()metoda disponibilă pentru noi care nu este atât de
diferit deciteș te_linii() except că scrie în loc să citească.

[Link]
2.
3.my_lines = ["Line one\n","Line two"]
[Link].scrie_linii(my_lines)

94
Apoi, în linia de comandă, rulează:

1$ py [Link] > [Link]

Dacă deschizi [Link], vei găsi că acesta conț ine ș irurile din lista de mai sus pe
două linii separate.

10.5 - Standard error


Mai există un flux standard pe care nu l-am acoperit încă ș i acesta este standard.
eroare (stderr). Este din nou un obiect de fiș ier în python, aș a că putem scrie în el. Este tipic
pentru programe care scriu mesaje de eroare ș i diagnostice în eroare standard.
În mod normal, eroarea standard este afiș ată pe terminalul care a pornit
program.

A avea fluxul de ieș ire standard rezolvă problema semi-predicatului prin


permiț ând distingerea între ieș iri ș i erori. Putem redirecț iona standard
eroare într-un flux de ieș ire diferit de ieș irea standard. (o fiș ier de jurnal pentru erori)
exemplu).
Asta e tot ce vreau să spun despre eroarea standard. Nu va trebui să ne facem griji în legătură cu asta.

încă o dată în această carte. E doar bine să ș tii despre toate fluxurile de date standard
avem acces la.

10.6 - Deschiderea ș i citirea fiș ierelor

În această secț iune vom examina deschiderea ș i citirea din fiș iere care sunt
stocate în stocare permanentă. Deș i fluxurile de date standard din
secț iunea anterioară sunt fiș iere, acestea erau stocate în RAM ș i erau deja deschise.

Când citim un fiș ier, iniț ializăm un obiect fiș ier care acț ionează ca un link de la
program pentru fiș ierul stocat pe disc.

Pentru a deschide un fiș ier, folosimdeschide()funcț


ie. Thedeschide()funcț ia ia două
argumente: Numele fiș ierului ș i modul în care fiș ierul trebuie deschis.
sintaxa este:deschide(<nume_fisier>, <mod>)

Există diverse moduri în care putem deschide un fiș ier, ne preocupă doar
cu patru dintre ei aici.

Cele patru moduri cu care ne vom ocupa sunt:

1.'r'Acest mod deschide un fiș ier doar pentru citire.

95
2.w- Acest mod deschide un fiș ier pentru scriere. Dacă fiș ierul nu există, îl creează.
un fiș ier nou cu numele specificat al fiș ierului. Dacă fiș ierul există ș i scriem
orice ceea ce a fost anterior în fiș ier este suprascris.
[Link]- Aceasta deschide un fiș ier în modul de adăugare. Dacă fiș ierul nu există, îl creează.
un fiș ier nou cu numele specificat. Dacă există, adăugăm la fiș ier
în loc să îl suprascrie.
4.'x'Aceasta deschide un fiș ier pentru creaț ie exclusivă, eș uând dacă acesta există deja
ș i aruncând unEroareFileExistă.

Odată ce fiș ierul este deschis, putem citi conț inutul său folosind metodele din secț iunea
3.4:citeste(), citeș te_linii() ș iciteș teLinie().
Să ne uităm la un exemplu de deschidere a unui fiș ier de pe disc ș i citirea conț inutului său
contents:

1.my_file = open('[Link]','r')
[Link] = my_file.readlines()
[Link](content)

Asiguraț i-vă că aveț i un fiș ier numit "[Link]" salvat în acelaș i director ca al dvs.
script ș i, în scopuri de demonstrare, asigură-te că are câteva linii de text în el.

La linia de comandă, rulează:

$ py [Link]
["Aceasta este linia unu.\n","Eu sunt linia doi.\n","Ș i eu sunt linia trei"]

Acum poț i vedea că conț inutul fiș ierului tău a fost citit cu succes.
Este în formă de listă, deoarece am folositciteste_linii()metodă.

10.7 - Scrierea în fiș iere ș i închiderea fiș ierelor

În secț iunea anterioară am examinat deschiderea fiș ierelor. Acum să vedem cum să
scrie-le ș i închide-le.

Aș a cum aț i putut ghici, scriem în fiș iere folosindscrie()metoda prin care ne-am întâlnit
în secț iunile anterioare. Pentru a scrie într-un fiș ier, acesta trebuie deschis în modul de scriere

mod.

Să vedem cum se scrie într-un fiș ier:

1.my_file = open('[Link]','w')
2.my_file.write("Sunt scris într-un fi ș ier\n")

Rulează acest script:

96
1$ py [Link]

Acum deschide fiș ierul numit [Link]. Nu-ț i face griji dacă nu a existat, unul va fi creat.
a fost creat. Ar trebui să vezi acum linia "Sunt scris într-un fiș ier" conț inută în
acefă dosar.

Acum trebuie să închidem fiș ierul.

Când un fiș ier este deschis, sistemul de operare alocă memorie pentru a urmări acest lucru.
starea fiș ierului ș i sistemul de operare nu pot realoca acea memorie până când
fiș ierul este închis. Dacă nu închidem fiș ierele deschise, atunci consumăm memorie
în mod inutil.
Când programul tău există, fiș ierul este închis automat, dar poate că noi nu o facem.
vrem să ieș im imediat după ce terminăm de citit ș i scris într-un fiș ier.

Închidem fiș ierele folosindînchide()funcț ie. Acest lucru este demonstrat mai jos:

1.my_file = open("[Link]","w")
2.my_file.write("Bună\n")
3.my_file.close()

Fiș ierul a fost acum închis ș i memoria poate fi realocată pentru alte utilizări.
A fi nevoit să deschizi fiș iere ș i să-ț i aminteș ti să le închizi poate deveni o adevărată bătaie de cap.

Putem folosi ceva numitcudeclaraț ie pentru a se ocupa de asta pentru noi.

Thecudeclaraț ia clarifică codul care anterior ar fi


foloseș tetry...finallyblocuri pentru a asigura că codul de curăț are este executat. Nu
îngrijoraț i-vă despreîncearcăș iîn cele din urmăne vom ocupa de ele un pic mai târziu, dar pentru moment, putem
foloseș tecupentru a gestiona închiderea fiș ierelor pentru noi.

[Link] open("[Link]","w") ca my_file:


2. my_file.write("Câteva texte aici")
3.
4.# RESTUL PROGRAMULUI TĂU AICI

Deci, ce se întâmplă aici? Putem vedea căcudeclaraț ie, dar avem ș i


uncadeclaraț ie. Thecadeclaraț ia este utilizată pentru a atribui obiectul returnat unui
nou identificator. În acest caz, deschidem un fiș ier ș i ni se returnează un obiect fiș ier.
obiectul fiș ierului este apoi atribuit variabileimy_filefolosindcadeclaraț ie.

97
Apoi facem tot ce trebuie să facem. În acest caz, scriem în fiș ier. Când noi
ieș ire dincublochează fiș ierul este închis. Deschiderea ș i închiderea fiș ierelor în acest mod este
de obicei, cum o fac majoritatea oamenilor.

O altă utilizare acaun enunț care ar putea clarifica lucrurile este, de exemplu, noi
importam modulul sys ș i nu ne plăcea cât de lung este numele „sys”
era (ș tiu că acesta este un exemplu prostesc, dar unele module au nume lungi), noi
pot să-l import ca atare:

[Link]ă sys ca s
[Link] = [Link]()

Acum, de fiecare dată când vrem să ne referim la modulul sys, îl numim după aliasul său,s.

10.8 - Aducerea tuturor împreună


We've learned a lot in this chapter so let's look at an example that puts
totul împreună.
Să presupunem că avem un fiș ier text care conț ine multe linii. Fiecare linie are un
numele studentului urmat de nota pe care a primit-o pentru o clasă specifică. Iată
o mostră din acel fiș ier text:
Liam 84
Noe 33
William 43
James 37
Logan 59

Ceea ce vrem să facem este să procesăm acest fiș ier ș i să ieș im într-un nou fiș ier dacă fiecare
studentul a trecut sau a picat cursul.

Ieș irea ar trebui să arate aș a:


Liam PASS
Noad EȘ EC
William PASS
James ESEC

Logan TRECE

98
Vrem să trecem numele fiș ierului de intrare ș i numele fiș ierului de ieș ire ca argumente la
scenariul ș i considerăm că o notă de promovare este sub 40.

Iată cum am putea face asta:


[Link] ț i sistemul

2.
[Link] = [Link][1] Fiș ierul sursă de intrare
[Link] = [Link][2] Fiș ierul de ieș ire
5.
[Link] open(src,'r') ca fin, open(dst,'a') ca fout: Deschide în modul de adăugare
7.
8. student = [Link]().strip() # Îndepărtează caracterul de întrerupere a liniei

9. whilestudent:
10.
11. student_data = [Link]() # ['Liam', '84'] for example
12.
13. name = student_data[0]
14. nota = int(date_studenti[1])
15.
16. daca mark < 40:
17. grade ="FAIL"
18. altfel:
19. grade ="PASS"
20.
21. [Link]('{:s} {:s}\n'.format(nume, nota)) Scrie în fiș ierul de ieș ire
le
22.
23. student = [Link]().strip() # Get the next student

Observaț i cum putem deschide mai multe fiș iere în acelaș i timp!

Administraț i acest lucru astfel:

$ py [Link] [Link] [Link]

Your output should now be:


Liam TRECE
Noah EȘ UAT
William PASS
James EȘ UEAZĂ

Logan PAS

Prelucrarea fiș ierelor este o sarcină comună, aș a cum am spus, aș a că obiș nuieș te-te cu ea, vei
probabil voi face asta mult!

10.9 - Exerciț ii
Notă importantă: Aceste întrebări sunt mai dificile decât cele anterioare ș i devin
considerabil mai dificile pe măsură ce progresează, în special întrebarea 4. Nu fi
descurajat, totuș i. Persistă în ele. Dacă reuș eș ti să finalizezi aceste 4
99
întrebări, eș ti pe calea de a deveni un mare dezvoltator ș i problemă
rezolvitor!

Întrebare 1
Scrieț i un program care multiplică un număr arbitrar de argumente din linia de comandă.

argumentele împreună. Argumentele vor fi numere (converteș te-le mai întâi).


Programul tău ar trebui să fie rulat după cum urmează:

$ py [Link] 5 99 32 ....

Pentru a verifica că soluț ia ta este corectă, ar trebui să obț ii următorul rezultat

$ py [Link] 8 8 9 3 2
3456

Întrebare 2
Scrie un program care citeș te linii din intrare standard (fără redirecț ionare) ș i
le trimite la ieș irea standard (fără redirecț ionare).

Întrebarea 3
Scrie un program care citeș te un fiș ier text ș i afiș ează (folosindprint()este bine) cum
multe cuvinte sunt conț inute în acel fiș ier. Numele fiș ierului de text ar trebui să fie
primit ca un argument de linie de comandă pentru scriptul tău.

Programul tău nu ar trebui să considere liniile goale ca fiind cuvinte ș i nu trebuie să-ț i faci griji

despre punctuaț ie. De exemplu, poț i consideraîncrederea fi singur


cuvânt.
Programul dumneavoastră ar trebui să fie executat astfel:

1$ py num_words.py [Link]

Pentru a testa că soluț ia ta este corectă, foloseș teA doua adresă inaugurală a
Abraham Lincoln701

Întrebarea 4
Scrie un program care citeș te conț inutul unui fiș ier. Fiecare linie va conț ine un
cuvânt sau expresie. Programul tău ar trebui să genereze (folosindprint()este bine) fie că
nu cada linie este un palindrom sau nu, "Adevărat" sau "Fals". Numele fiș ierului text
ar trebui să fie trecut ca un argument din linia de comandă la scriptul tău.

100
Un palindrom este un cuvânt sau o expresie care este la fel citită invers ca ș i înainte.
De exemplu, „racecar” este un palindrom, în timp ce „AddE” nu este.

Programul tău nu ar trebui să fie sensibil la majuscule: "Racecar" ar trebui să fie totuș i

considerat un palindrom. Spaț iile nu ar trebui să afecteze programul tău.


Consideraț i eliminarea caracterelor de spaț iu alb.

Programul tău ar trebui să fie rulat astfel:

$ py [Link] [Link]

To test that your solution is correct, use the following as your input text:
maș ină de curse
AdaugăE
HmllpH
A fost o maș ină sau o pisică pe care am văzut-o

Hannah
T poate apărea în contexte în care limba este jucată cu
Capabil am fost eu înainte să văd Elba

Observaț ie: eu nu sunt de acord. O dietă nu împiedică o obezitate. Eu mă hrănesc cu cod.

Folosind intrarea de mai sus, ieș irea ta ar trebui să fie:

Adevărat
Fals
Fals
Adevărat
Adevărat
Fals
Adevărat

Adevărat

Întrebarea 5
** ACEASTĂ ÎNTREBARE ESTE DIFICILĂ **

La fel ca întrebarea 3, scrie un program care citeș te un fiș ier text. De data aceasta, programul tău

ar trebui să afiș eze câte cuvinte unice sunt conț inute în fiș ier.

101
De data aceasta trebuie să îț i pese de punctuaț ie ș i soluț ia ta nu ar trebui să
fiț i sensibili la majuscule. De exemplu,încredereș iîncredereș iÎncrederear trebui să fie
considerat acelaș i cuvânt, prin urmare, ar trebui să existe o singură apariț ie a acelui cuvânt
fii înregistrat ca unic ș i dacă ai da pesteîncredereiarăș i, atunci
nu-l înregistra.
Programul tău ar trebui să fie rulat astfel:

$ py cuvinte_unice.py [Link]

Pentru a testa dacă soluț ia ta este corectă, foloseș teA doua adresă inaugurală a
Abraham Lincoln343

Indicaț ie 1: Aruncaț i o privire laș ir modul. În special,[Link]ț ie. Dacă


Dacă importaț i acest lucru, s-ar putea să îl puteț i folosi în avantajul dumneavoastră. Importaț i-l ca

urmeazădin string import punctuaț ieGăseș te


[Link]ț ie lucrează.

Sugestie 2: Soluț ia la acest exerciț iu poate folosi unele metode de ș iruri


pe care l-am analizat în capitolul despre ș iruri.

Indicaț ie 3: Folosirea unei a doua liste ar putea fi o idee bună!

102
Acest lucru ar putea părea puț in confuz, dar permite-mi să explic ce se întâmplă. Variabila iis
numit un contor (sau o variabilă de bucle) ș i controlează de câte ori se repetă bucla
iterează.

• Variabila este inițial 0, iar condiț ia evaluează ca adevărat, aș a că corpul de


bucla este executată.
• Tipăriț i valoarea variabilei în terminal ș i incrementaț i cu 1. (acum este 1
în loc de 0).
• Evaluate the condition again. It is stillTrueasiis still less than 5.
• Tipăriț i valoarea variabilei în terminal ș i incrementaț i-o cu 1. (este acum
2).
• Repetă paș ii de mai sus până la 5, în care cazul buclei este fals.
bucle se încheie ș i executăm orice instrucț iuni care urmează.

Ce-ar fi dacă am avea condiț ia asi < 10000? Cele patru linii de cod ar rămâne totuș i
ț ineț i apăsat, iar programul va număra de la 0 la 9999.

S-ar putea să te întrebi de ce am numărat de la 0, deoarece pare nenatural, dar există


un motive bune pentru asta. Explicaț ia pentru asta poate fi puț in prea tehnică pentru tine
în această etapă, dar permite-mi să dau un exemplu care, sper, să-l explice.

Îț i aminteș ti că am spus că poț i considera memoria ca pe niste sertare? Ei bine, haideț i să luăm asta

example:

-------------------------------------
| | | | | Fiecare "cubi ț ă" este o *loca ț ie de memorie*
-------------------------------------

-------------------------------------
| | | | | Fiecare are o *adresă*
-------------------------------------

-------------------------------------
| 32 | 44 | 89 | 12 | # Să presupunem că acestea sunt umplute cu valori
-------------------------------------

-------------------------------------
| 32 | 44 | 89 | 12 | # Să spunem că adresa primului
location is 2
-------------------------------------
^
|
2

AVEM NEVOIE DE O FORMULĂ PENTRU A ACCESA LOCATIA DE MEMORIE N DE AICI.


SĂ PRESUPUNEM CĂ VREM SĂ ACCESĂM LOCAȚ IA CARE DEȚ INE 89.
BINE, ACEASTA ESTE: adresa_curentă + 2 (2 + 2 = 4 care este adresa care conț ine
89)

37
Variabila de buclă este o variabilă temporară ș i rolul său este de a stoca un anumit
element pentru durata iteraț iei date. Să trecem prin exemplul nostru
ș i vezi cum funcț ionează asta.

1. Alegem primul element din listă ș i verificăm dacă există


2. O face, a ș a că o atribuim unei variabile numitenume.
3. Intrăm în corpul buclei ș i facem orice muncă avem nevoie să facem (printând
numele în acest caz).
4. Ne întoarcem la începutul buclei ș i repetăm pa ș ii 1 până la 4.
5. Vom ajunge la un punct în care nu există 'următorul element', caz în care noi
ieș i din buclă.

Ce-ar fi dacă ne-am afla într-o situaț ie în care nu aveam ceva peste ce să iterăm, dar
Am vrut să executăm un bloc de cod de un număr fix de ori?
Python oferă două funcț ii încorporate pentru a face acest lucru. Acestea sunt
theinterval()funcț ia ș ixrange()function.

Theinterval()funcț ia ia trei parametri, un start, un stop ș i un pas. The


start ș i step sunt opț ionale. Thegama()funcț ia construieș te o secvenț ă bazată pe
aceste parametrii.

Să ne uităm la el în acț iune:

[Link](5, 10):
2. print(i)

Executarea acestuia ne-ar oferi:

$ py [Link]
5
6
7
8
9

După cum poț i vedea, începem de la 5 ș i ajungem până la, dar fără a include 10. Dacă omitem
parametrul de start, atunci se va seta implicit la 0 ș i sunt sigur că poț i ghici asta
explică ce face parametrul step din cunoș tinț ele tale despre acesta în extensie
feliere.

104
Funcț ia range a construit o secvenț ă din5 către9 ș i iterăm peste
folosind bucla for.

11.2 - Dicț ionare


Până acum, am întâlnit multe tipuri diferite. De asemenea, am întâlnit Liste ș i Ș iruri.
Aceste două tipuri sunt exemple de structuri de date.În această secț iune vom...
uita-te la o altă structură de date încorporată în Python numită dicț ionar. Este de
tipdicț ionar.

Dicț ionarele sunt tipuri de colecț ii, dar nu secvenț e. Adică, elementele sale nu sunt
ordonate aș a cum sunt într-o listă sau într-un ș ir.

Dicț ionarele sunt uneori denumite hărț i sau hashmaps.


Un dicț ionar este o colecț ie de perechi cheie-valoare. Un dicț ionar implementează
o asociere de la o cheie la o valoare.

Acest lucru este ilustrat mai jos:

CHEI VALUES
____________ ____________________
| | | |
| "Tony" -|-------|-> "457-2344356" |
| | | |
| "Adam" -|-------|-> "359-5550983" |
| | | |

|----------| |------------------|

În acest exemplu, implementăm un catalog telefonic folosind un dicț ionar. Dacă căutăm
cheiaTony, suntem conduș i spre valoare"457-2344356".

Implementarea de bază a unui dicț ionar este concepută în aș a fel încât


Având o cheie; putem recupera valoarea asociată cu mare eficienț ă.

Complexitatea Big O pentru operaț ia de căutare este O(1). Este constantă. Nu...
indiferent cât de mare este dicț ionarul, timpul necesar pentru a căuta o valoare este întotdeauna
la fel. Magie, nu-i aș a? Ia-o ca pe o magie, nu voi intra în detalii despre cum o face.
în această carte, deoarece este un pic prea avansată pentru începători, dar eș ti mai mult decât
bine ai venit să vezi cum se face.

105
De asemenea, nu ș tim ordinea în care sunt stocate perechile cheie-valoare într-un Python
dicț ionar, aș a că nu scrie programe care să se bazeze pe ordinea lui. Dacă ai un
un dicț ionar care este acelaș i de fiecare dată când rulezi programul, ordinea va fi
diferit de fiecare dată.

Sintaxa pentru construirea unui dicț ionar este următoarea:

dicț ionarul_meu= {<key1> : <valoare1>, <cheie2> : <valoare2>, ...., <cheiaN> :


<valoareN>}

For the above phone book example, that would be done as follows:
phonebook = {"Tony":"457-2344356","Adam":"359-5550983"}Observaț i sintaxa pentru
dicț ionarele folosesc acolade în loc de paranteze pătrate.
Cu dicț ionarele, o cheie poate fi orice tip imutabil. Valorile pot fi de orice tip.
tip, inclusiv alte dicț ionare.

Dicț ionarul gol este:d = {}.

11.3 - Accesarea dicț ionarului


Putem accesa un dicț ionar prin chei pentru a recupera valori.

Acest lucru se face astfel:

>>> agendă telefonică= {"Tony":"457-2344356","Adam":"359-5550983"}


>>> phonebook["Tony"]
457-2344356

Dacă încercăm să accesăm un dicț ionar pe baza unei chei care nu există în cadrul
dictionar, primim o eroare. Această eroare este cunoscută ca oKeyErrorîn Python.

>>> agenț ie telefonică= {"Tony":"457-2344356","Adam":"359-5550983"}

>>> phonebook["Bob"]
Urmărire (apelul cel mai recent a eș uat):

Fiș ier "<stdin>", linia1, în <modul>

KeyError:'Bob'

Aminteș te-ț i, dicț ionarele nu sunt tipuri secvenț iate, aș a că nu putem accesa prin
poziț ie. Totuș i, putem folosi numere întregi ca chei, dar chiar ș i atunci, ele sunt doar
că; întregi.
>>> my_dict = {1"unu"3trei2:"two"}

106
>>> dictionarul_meu[3]
trei
>>> my_dict[0]
Urmărire a erorilor (cea mai recentă apelare a fost cea mai recentă):

Fiș ier "<stdin>", linie1, în <modul>


KeyError:0

Dacă avem o pereche cheie-valoare în care valoarea este o listă, putem indexa lista ca
urmează:
>>> my_dict = {"first": [2,4,8]}
>>> my_dict["first"][0]
2

11.4 - Adăugarea ș i eliminarea înregistrărilor

De asemenea, putem adăuga noi intrări într-un dicț ionar existent. Când adăugăm un nou
Introducere, adăugăm o nouă mapare a unui pereche cheie-valoare în dicț ionar.
Sintaxa pentru a face aceasta este:

dictionary[<key>] = <value>

Haideț i să vedem asta în acț iune

>>> my_dict = {}
>>> my_dict["one"]=1
>>> my_dict
{"one":1}

Aș a cum putem adăuga intrări în dicț ionar fără ca un nou dicț ionar să fie creat
de fiecare dată, dicț ionarele sunt tipuri mutabile.

Amintiț i-vă că cheile trebuie să fie de un tip mutabil, iar valorile pot fi de orice tip.

Asta va păcăli mulț i oameni.

Putem elimina înscrierile din dicț ionar folosinddeldeclaraț ie. Aceasta este
făcut astfel:
>>> carnet de telefoane= {"Tony":"457-2344356","Adam":"359-5550983"}
>>>delphonebook["Tony"]

107
În exemplul de mai sus, spunem, ș tergeț i intrarea din dicț ionar
a cui este cheiaTony.

11.5 - Operatori ș i metode pentru dicț ionare

Putem obț ine lungimea unui dicț ionar la fel cum facem cu ș irurile de caractere ș i
liste:
>>> agendă= {"Tony":"457-2344356","Adam":"359-5550983"}
>>>len(phonebook)

Aceasta returnează numărul de perechi cheie-valoare stocate în dicț ionar.

Putem folosiînoperator pentru a verifica dacă o cheie există sau nu în


dicț ionar

[Link] = {"Tony":"457-2344356","Adam":"359-5550983"}
[Link]ă "Tony" în agenda telefonică:

3. printaț i(phonebook["Tony"])
[Link]:
5. cheia nu există

Motivul pentru care am introdus dicț ionare în acest capitol este pentru că noi
use pentrubucle pentru a parcurge fiecare dintre cheile unui dicț ionar.

[Link] = {"Bill":"457-2344356","Adam":"359-5550983"}
2.
[Link]:
4. {} numărul este {}.

Codul de mai sus ar produce următorul output:


Numărul lui Bill este 457-2344356.

Numărul lui Adam este 359-5550983.

Putem recupera o listă a cheilor sau valorilor unui dicț ionar folosind fie
thechei()metodă sauvalori()metodă respectivă.
>>> agendă telefonică= {"Bill":"457-2344356","Adam":"359-5550983"}
>>> [Link]()
dict_keys(['Bill','Adam'])
>>> [Link]()
dict_values(['457-2344356','359-5550983'])

108
Acestea nu sunt cu adevărat liste, deoarece nu le putem indexa, dar putem itera peste ele.
folosind unpentruciclare.

Vreau să introduc pe scurt o altă structură de date. Se numeș te tuple. Nu voi


nu intra în detalii încă, dar este practic o listă imuabilă. Putem indexa
în el, dar nu poate schimba (la fel ca un ș ir).
Motivul pentru care trebuie să te informez despre asta aici este pentru că putem recupera un
listă de tupluri folosind metoda dicț ionaruluiarticole().
Acest lucru funcț ionează astfel:

>>> dict-ul meu= {"one":1,"two":2}


>>> my_dict.items()

dict_items([('two',2unul1)])

Putem observa că tuplurile au forma(e1, e2, ....., en) unde e1....en sunt
elemente.

La fel ca o listă cu paranteze în loc de paranteze pătrate.

Putem itera ș i peste acestea. Funcț ionează astfel:


my_dict = {"one":1,"two":2}

pentru(k, v)înmy_dict.items():
print("Cheie: {} ș i Valoare: {}".format(k, v))

Aminteș te-ț i, [Link]() returnează o 'listă' de tupluri, fiecare tuplu conț inând două
elemente, cheia ș i valoarea. Când spunempentru (k, v) în
my_dict.items()ăam spunem esenț ial pentru fiecare tuplă din lista tuplelor,
atribuiekla elementul din prima poziț ie din tuplu ș ivla elementul din
a doua poziț ie. Voi ilustra asta mai jos:
(k, v)
| |
V V
("one", 1)

keste asignat launuș iveste atribuit la1.

Executarea codului de mai sus produce următoarea ieș ire:

Key: two and Value: 2

109
Key: one and Value: 1

Observaț i cum nu sunt în aceeaș i ordine în care au apărut când am creat


dicț ionar.

11.6 - Sortarea dicț ionarelor


Putem sorta un dicț ionar pe baza valorilor cheilor sale folosindsortat
metodăSă vedem cum poate fi făcut acest lucru:

agendă telefonică= {"Bill":"457-2344356","Adam":"359-5550983"}

pentru(k, v)sortate([Link]()):
print("Cheie: {} ș i Valoare: {}".format(k, v))

Rularea acestuia ar da următoarea ieș ire:


12Key: Adam and Value: 359-5550983

Key: Bill and Value: 457-2344356

Aș a cum puteț i vedea, dicț ionarul a fost sortat în funcț ie de chei. Deoarece
cheile sunt ș iruri de caractere, ele sunt sortate lexicografic.

De asemenea, putem sorta după valori, totuș i, nu avem cunoș tinț ele necesare pentru a face asta.
încă. Ne vom întoarce la asta în capitolul despre funcț ii.

Putem totuș i inversa ordinea în care sunt [Link]()funcț ie


are un parametru opț ional numitinversPutem seta acest lucru laAdevăratș i
dicț ionarul va fi sortat în ordine inversă pe baza cheilor.
agendă telefonică= {"Bill":"457-2344356","Adam":"359-5550983"}

pentru(k, v) sortate([Link](), invers=Adevărat):

print("Cheie: {} ș i Valoare: {}".format(k, v))

Aceasta ne va oferi următoarea ieș ire:


Key: Bill and Value: 457-2344356
Key: Adam and Value: 359-5550983

110
11.7 - Exerciț ii
Întrebarea 1
Scrie un program care citeș te un fiș ier. Fiș ierul va conț ine un număr de articole.
stocat într-un magazin ș i numărul de fiecare articol disponibil. Programul tău
ar trebui să analizeze fiș ierul ș i să construiască un dicț ionar din acesta, apoi să scoată stocul
disponibil în ordine alfabetică ș i într-un format specific. Puteț i folosi
următoarele ca fiș ier text de intrare:

Portocale 12
Mere 10
Pere 22
Lapte 7
Sticle de apă 33
Batoane de ciocolată 11

Băuturi energizante 8

Ieș irea programului tău ar trebui să arate astfel:

Apples : 10
Chocolate Bars : 11
Energy Drinks : 8
Milk : 7
Oranges : 12
Pears : 22
Water Bottles : 33

Indice: Aflaț i lungimea celei mai lungi chei.

Întrebarea 2
Scrieț i un program care citeș te un fiș ier text. Fiș ierul este o listă de detalii de contact pentru
oameni. Cu fiecare contact, primeș ti numele, numărul de telefon ș i adresa de email
adresă. Dicț ionarul tău ar trebui să fie o mapare de la numele contactelor la emailuri
ș i numărul de telefon pentru acel contact. Programul tău ar trebui apoi să întrebe utilizatorul

intrare. Intrarea ar trebui să fie un nume unic. Dacă numele poate fi găsit în
contact list then output the name and contact details for that person,
altfel ieș ireNiciun contact cu acel nume.

111
Fiș ierul listei de contacte este:

Liam 345-45643454 liam@[Link]


Noah 324-43576413 [Link]@[Link]
Tony 987-56543239 tony@[Link]

Bert 654-99275234 [Link]@[Link]

Dacă utilizatorul introduce apoi următoarele nume în această ordine:

Tony
Noe
Ion
Annie
Bert

Programul tău ar trebui să ofere următoarea ieș ire:

Name: Tony
Email: tony@[Link]
Phone: 987-56543239

Name: Noah
Email: [Link]@[Link]
Phone: 324-43576413

Fără contact cu acel nume

Niciun contact cu acel nume

Name: Bert
Email: [Link]@[Link]
Phone: 654-99275234

Aceste detalii ar trebui să fie tipărite câte una pe măsură ce utilizatorul introduce numele, nu
în vrac aș a cum am menț ionat mai sus.

Întrebarea 3

112
În capitolul precedent am încercat să numărăm câte cuvinte erau conț inute
într-un fragment de text. În această întrebare trebuie să faci acelaș i lucru, cu toate că
should output how many times each word occurred in the text.
Din nou, punctuaț ia contează. De data aceasta dorim să eliminăm orice punctuaț ie
înconjurând un cuvânt. Programul tău nu ar trebui să fie sensibil la majuscule

oriBunăș isalutar trebui să conteze ca aceeaș i cuvânt. Cu toate acestea, ceva


caJohnș ialuiJohnnu ar trebui socotită ca aceeaș i cuvânt. Cu alte cuvinte,
stripareț i caracterele de punctuaț ie de la început ș i de la sfârș it.

Programul dumneavoastră ar trebui să fie rulat astfel:

$ py dict_count.py [Link]

Pentru a verifica că soluț ia ta este corectă, foloseș teAl doilea discurs inaugural al
Abraham Lincolnaceasta este o
exemplu din afară):
.
.
.
58
oath : 1
de : 22
presidential : 1
office : 1
acolo : 2
este : 6
mai puț in : 2

occasion : 2
pentru : 9

an : 3
extins : 1
address : 2
decât: 4
.
.

113
.

You need not format the output. The length of your dictionary should be 701.

Întrebare 4
Scrie un program care ia două dicț ionare ș i iese intersecț ia lor.
intersecț ia a două dicț ionare ar trebui să fie un al treilea dicț ionar care conț ine cheia-
perechi de valori care sunt prezente în ambele dicț ionare. Poț i să durezi
codifica aceste două dicț ionare în. Nu este necesar să fie citite din nicio parte.

Rulaț i scriptul dvs. astfel:


$ py [Link]

Pentru a testa dacă soluț ia ta este corectă, poț i rula programul tău cu cele două
următoarele dicț ionare:
d1= {"k1":True, "k2":True, "k3":True, "k4":True}
d2= {"k6":True, "k2":True, "k5":True, "k1":True, "k8":True, "k4":
Adevărat

Your program should output the following dictionary:


intersecț ie= {"k2":True, "k1":True, "k4":True}

114
Capitolul 12 - Funcț ii ș i Module
12.1 - Ce sunt funcț iile?
În Python, o funcț ie este un cod care primeș te un input, efectuează unele
computare ș i produce o ieș ire. În programare, o funcț ie este o
bloc reutilizabil de cod care îndeplineș te o sarcină specifică.

Putem apela o funcț ie de mai multe ori în timpul execuț iei unui program. Avem
am făcut asta de multe ori în întreaga această carte deja.

Unele dintre funcț iile comune cu care ne-am întâlnit suntlen()ș iprint(). Când noi
vrem să ș tim lungimea a ceva ce transmitem acelui ceva
cellen()funcț ie de exemplu.

Când vrem să imprimăm ceva în fereastra terminalului


noi numimprint()funcț ie.

Am întâlnit de asemenea metode. Metodele sunt funcț ii care sunt asociate cu un


object. For example the format()metoda operează pe ș iruri. Metodele sunt
implementate în acelaș i mod ca funcț iile ș i sunt în esenț ă funcț ii care
operam asupra obiectelor asociate, dar vom reveni la acelea mai târziu.

12.2 - Definirea propriilor noastre funcț ii

Cel mai adesea, funcț iile încorporate Python nu sunt suficiente. Să luăm în considerare...
algoritm de căutare liniară, de exemplu. Este posibil să dorim să căutăm un ș ir de mai multe ori.

de-a lungul programului nostru. Până acum ar fi trebuit să scriem


algoritmul de căutare liniară din nou ș i din nou. Programatorii nu le place să repete
se repetă, aș a că dacă se găsesc repetând acelaș i cod, ei vor
pune acel cod într-o funcț ie. Aceasta înseamnă că, de fiecare dată când vrem să folosim acel fragment

de cod putem să îl numim aș a cum facem cuprint()de exemplu.

Definim funcț iile noastre folosinddefcuvânt cheie. Să aruncăm o privire asupra unei funcț ii
care afiș ează "Salut, lume!" pe ecran.

[Link]():
2. Salut, lume!

Mai sus am definit, folosinddef, o nouă funcț ie numită salut(). Când


apelăm funcț ia noastră, blocul de cod al funcț iei se va executa, în acest caz doar

115
tipăriț iSalut, lume!pe ecran. Această funcț ie poate fi utilizată astfel în cadrul
codul nostru:

[Link]():
2. Salut, lume!
3.
[Link]ă()

Ultima linie de mai sus apelează funcț ia noastră. Acest lucru ar trebui să fie familiar deoarece ai apelat

alte funcț ii de multe ori acum!

Sintaxa pentru definirea funcț iilor este:

deffunc_name(arg1, arg2, ...., argn):


# cod funcț ie
returnaț iresult

Îț i voi explica cearg1, arg2, ..., argneste în secț iunea următoare, dar să luăm un
uită-te lareturnaredeclaraț ie.

În prima noastră funcț ie nu am primit un rezultat, pur ș i simplu a imprimat ceva.


ecranul. Să scriem o funcț ie care vaîntoarceBună, lume!

[Link]():
2. Salut, lume!

Putem folosi această funcț ie după cum urmează:

[Link]():
2. Salut, lume!
3.
4.x = salut()
[Link](x)
6.
7.# ALTERNATIV
[Link](hello())

În această funcț ie, ș irulBună, lume!este returnat apelantului funcț iei.


Deoarece funcț ia returnează o valoare, se aș teaptă ca apelantul acesteia să colecteze acea valoare.
Mai sus vedem că apelantul colectează valoarea returnată ș i o stochează înxPuteț i
vezi căprint()funcț ia colectează, de asemenea, valoarea returnată de
thesalut()funcț ie.

12.3 - Argumente ș i parametrii


Am văzut funcț ii precumlen()care ia argumente precum un ș ir sau
dicț ionar ș i returnează-i lungimea.

116
În secț iunea anterioară, am analizat sintaxa pentru o funcț ie. În aceasta, am avut
ceva de genul:
def myFunc(arg1, arg2, arg3):
#

Thearg1, arg2, arg3se numesc parametrii funcț iilor. O funcț ie


parameter is like a variable that is local to the function thus cannot be
referit în afara acestei funcț ii. Un alt nume pentru un parametru este un formal
parametru. Dacă funcț ia noastră are un parametru formal, atunci trebuie să trecem un
valoare pe care o oferim funcț iei atunci când o apelăm. Această valoare se numeș te argument. O altă
numele pentru un argument este un parametru actual.

Să ne uităm la un exemplu de funcț ie care adună două numere:

[Link](x, y):
2. rezultatul = x + y
3. returnresult
4.
[Link]ă(add(5, 7))

În funcț ia de mai sus,xș iy în definiț ia funcț iei se numesc


parametrii.

Când apelăm funcț ia, transmitem5si7funcț iei. Acestea sunt


argumentele pe care le-am furnizat funcț iei.

Variabilaresult este de asemenea local la funcț ie ș i nu poate fi referit din


în afara funcț iei.
Argumentele ș i parametrii sunt, în mod implicit, asociaț i în funcț ie de poziț ie. În acest
exemplu, primul argument (5) este copiat în primul parametru (x).... ș i aș a
pe.

Mai devreme am analizat o funcț ie care a imprimat hello world. Funcț iile care fac
procedurile care nu returnează valori sunt numite proceduri.

O procedură schimbă starea programului nostru. De exemplu, acestea pot actualiza


valori ale variabilelor, afiș ează ceva pe ecran sau actualizează un fiș ier.

Funcț iile care returnează o valoare inspectează starea programului nostru. Ele returnează o
valoare bazată pe inspectia lor.

117
Aminteș te-ț i deîmpărț i()metodă? Am spus că dacă nu trecem niciun argument la aceasta
metoda, atunci va împărț i un ș ir pe baza spaț iului. Aceasta se numeș te
un argument implicit.
Un argument implicit este un parametru care presupune o valoare implicită dacă nu este specificată una.

furnizată atunci când apelantul invocă funcț ia.

Mai jos este un exemplu de funcț ie cu argumente implicite:

1.defprint_circle_info(r, x=0, y=0):


2. print("(x, y) coordonate: {}, {} Raza: {}".format(x, y, r))

În funcț ia de mai sus, trebuie să trecem un raadius ca argument atunci când o apelăm.
Cu toate acestea, nu trebuie să trecem o coordonată x sau y. Dacă nu trecem o coordonată x sau y.
coeficient, funcț ia noastră implicitează aceste valori la 0.

Dacă transmitem coordonatele x ș i y, valorile pe care le transmitem vor fi atribuite la


parametrii x ș i y.

Putem defini de asemenea funcț ii care au un număr variabil de argumente.

1.defmy_function(*argv):
2. pentru argument argv:

3. print(arg)
4.
5.my_function("prima","a doua","chiar a treia")

Ieș irea din apelarea acestei funcț ii ar fi:


primul
al doilea
chiar ș i o treime

În exemplul de mai sus,argveste un nume arbitrar pe care l-am ales ca parametru


numele. Acesta* în prealabil indică faptul că este un parametru de lungime variabilă.

Avem de asemenea parametrii cu lungime variabilă pentru cuvinte cheie.

1.defmy_function(**kwargs):
2. fork, vinkwargs:
3. print("{} : {}".format(k, v))
4.
5.my_function(first="Hello", second="World")

Ieşirea ar fi astfel:
lume
first : Hello

118
După cum probabil îț i poț i da seama,kwargseste un dicț ionar. Indicam că este un cuvânt cheie
parametru de lungime variabilă de către**înainte de numele variabilei.

Atât parametrii normali, cât ș i cei cu lungime variabilă pe bază de cuvinte cheie trebuie plasaț i la sfârș it

a listei parametrilor atunci când definiț i parametrii funcț iilor dvs. Există bine
motivul pentru aceasta. Dacă am fi avutdef func(x, y, *argv, z)nu am ș ti
unde*argvs-a încheiat.

Voi spune să fii prudent când foloseș ti parametrii de lungime variabilă. Ei


ar trebui folosite doar atunci când ai un motiv bun să le foloseș ti (ș i acesta nu este
foarte des).

12.4 - Domeniul de valabilitate al variabilelor

Nu toate variabilele sunt accesibile din toate părț ile programului tău. Partea unui
programul în care o variabilă este accesibilă se numeș te domeniul său. O variabilă care este
definit în corpul principal al unui fiș ier se numeș te variabilă globală. Va fi vizibilă
pe tot parcursul fiș ierului ș i orice fiș ier care importă acel fiș ier.

Variabilele globale pot avea consecinț e neintenț ionate din cauza „domeniului” lor
(ele pot fi accesate de oriunde). Există doar foarte speciale
circumstanț ele în care ar trebui să folosim variabile globale în software-ul pe care îl facem în

viaț a reală.
Variabilele care sunt definite în interiorul blocurilor de cod sunt locale acestui bloc.
Un bloc este o construcț ie care delimitează domeniul de aplicare al oricărei declaraț ii în interiorul său. În

Python, o variabilă definită într-o funcț ie este locală acelei funcț ii. Este
accesibil din momentul în care este definit până la sfârș itul acelei funcț ii.

Parametrii formali ai unei funcț ii acț ionează ca variabile locale. Cu toate acestea,
atribuț iile la un parametru nu pot afecta niciodată argumentul asociat decât dacă
sunt un tip modificabil, pe care l-ai văzut în secț iunea anterioară.

12. 5 - Default mutable argument trap


Consideraț i acest cod ș i ieș irea sa:

1.defadd_to_list(cuvânt, listă_de_cuvinte=[])
2. word_list.append(word)
3. lista_cuvintelor_returnate

4.
[Link]():
6. word ="apple"
7. tlist = adaugă_la_listă(cuvânt)
8. print(tlist)

119
9. word ="orange"
10. tlist = add_to_list(word, ['pear'])
11. printa(tlist)
12. word ="banana"
13. tlist = adaugă_la_listă(cuvânt)
14. print(tlist)
15.
[Link]()

$ py [Link]
măr
["pară","portocală"]

["măr","banana"]

Să ne uităm de ce acest comportament este ciudat. Observăm că al doilea parametru


cătreadauga_la_lista()este opț ional (indicat prin valoarea implicită[]). Dacă nu există argument
dacă acest parametru este furnizat atunci când se apelează funcț ia, atunci acel parametru
îș i asumă valoarea de[], lista goală.

Prima dată când apelăm funcț ia ș i îi transmitemmăr, ne întoarcem["măr"].


Asta este bine ș i este ceea ce ne-am aș teptat. A doua oară când apelăm funcț ia
ș i dă-i drumulportocalăș i o listă de['pere'], primim înapoi listapere
portocalie. Acesta este de asemenea în regulă ș i ceea ce ne-am aș teptat. A treia oară, totuș i, noi
a avea un comportament neaș teptat.

De ce estemărulîn listă, dacă am apelat funcț ia ș i am trecutbananăș i fără listă.


Cu siguranț ă ar trebui să ne î[Link] se numeș te mutabil implicit
capcană argument ș i nu, nu este un bug.

Lista goală este iniț ializată o singură dată de Python. Este iniț ializată când
thedefpentru acea funcț ie este întâlnită pentru prima dată. Aceasta înseamnă că lista are memorie
ș i orice adăugat la acesta va rămâne acolo.

Concluzia de aici este să nu folosiț i tipuri mutable ca argumente implicite.


În schimb, ocoliț i-l astfel:

1.defadd_to_list(cuvânt, listă_de_cuvinte=None):
2. dacă lista_de_cuvinte este None:

3. word_list = []
4. word_list.append(word)
5. returnword_list
6.
[Link]():
8. word ="apple"
9. tlist = adaugă_la_listă(cuvânt)
10. print(tlist)
11. word ="orange"
12. tlist = adaugă_la_listă(cuvânt, ['pară'])
13. print(tlist)

120
14. word ="banana"
15. tlist = adaugă_la_listă(cuvânt)
16. print(tlist)
17.
[Link]()

Acest lucru va oferi:

măr
["pere","portocale"]
["banana"]

Ș i aceasta este ceea ce ne-am aș teptat prima dată.

Nimiceste un tip special. Este un obiect care indică lipsa valorii ș i este
un tip imutabil. De fapt,Nimicse întoarce dintr-o funcț ie dacă nu există return
declaraț ie în acea funcț ie adică o procedură.

12.6 - Ce sunt modulele?


Am menț ionat pe scurt modulele înainte ș i am spus că un modul este pur ș i simplu un fiș ier
constând din cod Python. Un modul poate defini funcț ii, clase ș i
variabile. Un modul poate conț ine, de asemenea, cod executabil.

Modulele îț i permit să organizezi logic codul tău Python. Gruparea codului în


modulele fac mai uș or de înț eles ș i de utilizat codul tău. Nu este neobiș nuit
pentru un proiect software să se întindă pe sute de fiș iere.

Puteț i importa module folosindimportadeclaraț ia pe care am văzut-o când


importare{"sys":"sistem"}ș iș ir.

Putem importa atribute specifice din module folosindde lakeyword


de exempludin string importa semnele de punctuaț ieDe asemenea, putem importa toate atributele dintr-un

modul folosind* de exempludin string import*.

Când importăm un modul, interpretul Python caută modulul în


în următoarea manieră:

• InterpretorulPython caută în directorul curent.


• Dacă nu este acolo, atunci interpretul caută în fiecare director din shell
variabila PYTHONPATH
• În cele din urmă, dacă nu este acolo, atunci interpretul caută calea implicită.
Linux, acesta este în mod normal/usr/local/lib/python.

121
12.7 - Crearea propriilor noastre module

Putem crea module proprii pentru a organiza logic codul nostru. Să spunem că
vrem să creăm un modul care conț ine unele funcț ii matematice. Facem asta ca
urmează:

1.# [Link]
2.
[Link](x, y):
4. returnx + y
5.
[Link](x, y)
7. returnează x * y
8.
[Link]():
10. print(adaugă(x, y))
11. print(multiply(x, y))
12.
13.if__name__=="__main__":
[Link]()

Theadauga()ș iînmulț iț i() funcț iile sunt bune ș i am întâlnit altele similare
funcț iile înainte. Theprincipala()function we have also come across in a previous
secț iune dardacă __name__=="__main__":, nu am dat peste înainte.

Când executi un program direct din linia de comandă (aș a cum ai fost
executând), interpretul Python setează o variabilă specială pentru acel script. Aceasta
variabila este__name__Când un script este executat direct, acea variabilă este setată
la"__main__", altfel, dacă este importat, de exemplu, atunci este setat la
numele modulului,matematicăîn acest caz.

Includem dacădeclaraț ie pentru a verifica această variabilă, deoarece uneori vrem să


testează codul nostru sau avem vreo modalitate de a demonstra modulul nostru. Dacă îl rulăm direct

atunciprincipal()funcț ia este executată. Altfel, dacă importăm acest modul, atunci


theprincipal()funcț ia nu este executată.
Este o practică bună să includeț i această verificare în scripturile dvs. Această verificare este de asemenea

de obicei situat la sfârș itul scriptului.

Modul în care Python gestionează__name__ variabila s-a schimbat în Python 3.7. Este
acum subPEP 567. La suprafaț ă, nimic nu s-a schimbat drastic.

122
12.8 - Exerciț ii
Când îndeplineș ti aceste exerciț ii, foloseș te următorul model atunci când scrii
scripts:

1.# func ț ii ș i constante


2.
[Link]():
4. # Cod de test
5. Orice altceva care nu ar trebui să se întâmple atunci când codul tău este importat
6.
7.if__name__ =="__main__":
[Link]()

Dacă ț i se cere să scrii un modul, atunci ar trebui să salvezi modulul în


aceeaș i direcț ie ca scriptul tău de testare.

Întrebarea 1
Scrieț i un modul [Link] conț ine funcț ii care implementează
atât sortarea prin selecț ie cât ș i sortarea prin inserț ie adică modul tău ([Link]) ar trebui să conț ină

osortare_selecț ie(a) funcț ie ș i unsortare_inserare(a)function. Your function


ar trebui să returneze valorile, nu să le afiș eze.

Modulul tău trebuie să fie importat ș i rulat astfel în alt script


[Link]:

[Link]
2.
3.a = [5, 6, 3, 8, 7, 2]
[Link](sorting.selection_sort(a))
5.a = [5, 6, 3, 8, 7, 2]
[Link]ă(sorting.insertion_sort(a))

$ py [Link]
[2, 3, 5, 6, 7, 8]
[2, 3, 5, 6, 7, 8]

Întrebarea 2
Scrie un modul [Link] modul ar trebui să includă următoarele
functions:

• adauga()
• înmulț iț i()

123
• împărț iț i()
• scade()

Theadauga(), înmulț iț i()ș iscade()funcț iile ar trebui să fie capabile să gestioneze un


număr arbitrar de argumente.împărț iț i() ar trebui să accepte doar 2 argumente. Al tău
funcț ia ar trebui să returneze valorile calculate, nu să le afiș eze.

Modulul tău ar trebui să fie importat ș i rulat după cum urmează într-un alt script
[Link]

[Link] aritmetic import*


2.
[Link]ă(adaugă(4, 6, 7, 2, 3))
[Link](adaugă(3, 2))
5.
[Link](subtract(5, 6, 8, 9))
[Link]ă(subtract(3, 2))
8.
[Link](divide(6, 3))
10.
[Link](multiply(2, 3))
[Link](multiply(2, 3, 3))

$ py [Link]
22
5
-18
1
2
6

18

Întrebare 3
Scrie o funcț ie numitălength()care imitălen()funcț ie. Funcț ia ta
ar trebui să funcț ioneze pentru ș iruri, dicț ionare ș i [Link]()ar trebui să dureze doar 1
argumentaț i ș i returnaț i lungimea structurii de date transmise.
Funcț ia dumneavoastră ar trebui să fie testată cu următoarele:

1.a = [5, 3, 4, 1, 2, 3]
[Link]ă(lungimea(a))
3.
4.a = []
[Link](lungimea(a))
6.

124
7.d = {}
[Link]ă(len(d))
9.
10.d = {"one":True,"two":True}
[Link](length(d))
12.
13.s ="This is a string"
[Link](lungimea(s))
15.
16.s = ""
[Link](len(s))

$ py [Link]
6
0
0
2
16

Întrebarea 4
Scrie o funcț ie numităfib() care calculează ș i returnează n-lea Fibonacci
număr. Funcț ia ta ar trebui să ia 1 argument, numărul Fibonacci pe care îl
vrea să calculeze.

Funcț ia ta ar trebui să fie testată cu următoarele:

[Link](fib(3))
[Link](fib(0))
[Link](fib(1))
[Link](fib(10))
[Link](fib(13))

$ py [Link]
3
1
1
89

377

Aminteș te-ț i:
fib(n)=fib(n−1)+fib(n−2)

fib(0)=1

125
fib(1)=1

Întrebarea 5
Scrie o funcț ie numităciteș te_fiș ier() care ia un singur argument, un nume de fiș ier
(ca un ș ir), ș i returnează conț inutul fiș ierului sub formă de listă cu fiecare element
în listă fiind un singur rând din fiș ier.

Funcț ia ta ar trebui să fie apelată astfel:

[Link] = read_file("[Link]")

Întrebarea 6
Scrie o procedură de funcț ie numitărep_all()care ia 3 argumente, o listă de
întregi ș i 2 numere. Procedura ta ar trebui să înlocuiască toate apariț iile ale
primul număr cu al doilea.

Apelarea funcț iei tale astfel ș i imprimarea listei ulterior ar trebui să


produce următoarele:

1.a = [4, 2, 3, 3, 7, 8]
[Link]ă_tot(a, 3, 10)
[Link](a)

$ py [Link]
[4, 2, 10, 10, 7, 8]

126
Capitolul 13 - Căutare binară
13.1 - Joc de ghicit numere
Să presupunem că avem un tablou sortat de lungime 100,000. Să presupunem în continuare
cineva a ales un număr din acel tablou, la întâmplare ș i noi nu
ș tim ce este. Ni se oferă 20 de încercări pentru a ghici răspunsul. Acest lucru poate părea
imposibil ș i că avem doar noroc de partea noastră.
Putem folosi cunoș tinț ele pe care le avem până acum pentru a scrie o funcț ie care să facă o estimare asupra acestui lucru,

ș i avem câteva modalităț i de a face acest lucru.

Să analizăm două modalităț i prin care am putea încerca acest lucru. Prima este căutarea liniară.

[Link]
2.
[Link] = [xforxinrange(0, 100000)]
[Link] = randint(0, len(arr))
5.
6.i = 0
7.în timp ce i < 20 ș i i != secret:
8. i += 1
9.
[Link] < 20:
11. print("Numărul secret este " + str(i))
12.încazcontrar:

13. Noroc prost, nu ai ghicit numărul secret

Prima linie importărandint()funcț ia dinaleatoriumodul care


primeș te două argumente întregi ș i returnează un întreg aleatoriu între
argumente.

A doua linie construieș te array-ul folosind ceva numit listă


înț elegere. Ne vom întoarce la acestea curând.

A treia linie alege acel număr aleator ca numărul secret ș i restul


codul este o căutare liniară standard pentru a încerca să găseș ti secretul.

În mod evident, aceasta este o idee teribilă deoarece numărul secret trebuie să fie între 0 ș i
20 which has a 20/100000 chance of happening.
O altă abordare pe care am putea să o adoptăm este să facem 10 ghiciri aleatorii.

127
[Link]
[Link] = [xforxinrange(0, 100000)]
[Link] = randint(0, len(arr))
4.
[Link] = randint(0, len(arr))
6.i = 1
7. în timp ce i < 20 ș i ghicirea != secret:
8. ghicire = randint(0, len(arr))
9. i += 1
10.
[Link] < 20:
12. Numărul secret este
13. altfel:
14. Noroc prost, nu ai ghicit numărul secret

O abordare mai bună? Poate, dar putem face mult mai bine. De fapt, putem ghici
număr în cadrul a 20 de încercări de fiecare dată fără eș ec. Folosim un algoritm nou
a fost denumit Căutare Binara pentru a face asta.

13.2 - Căutare binară


Una dintre presupunerile făcute în secț iunea anterioară a fost că lista era
sortat. Ș tiind că lista este sortată, ne permite să profităm de acest fapt.
În această secț iune, vom analiza cum facem asta folosind un nou algoritm de căutare.
cunoscut sub numele de căutare binară.

Permiteț i-mi să ilustrez cum funcț ionează căutarea binară:

2 4 9 12 34 35 77
|_____________________| # Numărul pe care încercam să-l ghicim este aici

2 4 9 12 34 35 77
| low | high
|_____________________| Vom numi aceste două poziț ii joase ș i
înalt

2 4 9 12 34 35 77
| low înalt

|_____________________| Numărul este undeva între mic ș i


înalt

2 4 9 12 34 35 77
scăzut înalt De asemenea, suntem capabili să calculăm indicele
pentru

128
|_____________________| numărul din mijlocul valorilor scăzute ș i ridicate

2 4 9 12 34 35 77
scăzut mijloc înalt De asemenea, suntem capabili să calculăm indicele
pentru
|_________|____________| numărul din mijlocul scăzut ș i înalt

#
Presupunem că numărul pe care îl căutăm este 4
#

2 4 9 12 34 35 77
scăzut mijloc înalt De asemenea, suntem capabili să calculăm indexul
pentru
|_________|____________| numărul din mijlocul valorilor mici ș i mari

2 4 9 12 34 35 77
scăzut mijloc ridicat Întrucât lista este sortată, putem verifica dacă
the
|_________|____________| # numărul din 'mijloc' este <= sau > 4

2 4 9 12 34 35 77

scăzut mijloc înalt În acest caz, 4 este < 12, deci nu avem nevoie
la
|_________|____________| nu te deranja să cauț i nimic deasupra mediei
index

2 4 9 12
| low | high Aș a că am tăiat acea porț iune din listă
|_________| ș i fă din mijloc noul înalt

2 4 9 12
scăzut | high Repetaț i procesul,

129
|_________| împărț ind continuu lista la jumătate până când
condiț ie
aceeaș i valoare scăzută < valoare mare eș uează adică valoare scăzută == valoare mare

So, our approach here is:

• Găseș te punctul mediu întreînaltș iscăzut


• Ajustaț iscăzutsauînaltîn funcț ie de ceea ce căutăm
mai mic sau egal cu (<=) sau mai mare decât (>) valoarea medie.

Calculăm punctul de mijloc obț inând media dintre minim ș i maxim adică(scăzut +
înalt) // 2. Observaț i că facem o împărț ire întreagă aici, deci vom rotunji în jos dacă
există un loc zecimal.

În secț iunea următoare, vom analiza implementarea căutării binare

13.3 - Implementarea căutării binare


În secț iunea anterioară am analizat cum funcț ionează căutarea binară. Acum avem nevoie
să-l codifice.

Aproximativ, doar 10% dintre dezvoltatori sunt capabili să scrieț i corect căutarea binară.
Există o mică scurgere în mijlocul ei, aș a că trebuie să fim atenț i pentru ca turma noastră.
soluț ia funcț ionează corect în toate cazurile.

Mai jos este implementarea comentată a căutării binare:

defbinar_căutare(arr, elem):
2. low = 0 Defineț i valoarea iniț ială scăzută.
3. high = len(arr) Definiț i valoarea iniț ială mare.
4.
5. în timp ce low < high: Condiț ia care trebuie să fie adevărată.
6. mid = (low + high) // 2 # Calculează indexul mediu.
7.
8. dacă ifarr[mid] < elem: Verificaț i dacă valoarea se află în prima sau a doua jumătate
.
9. low = mid + 1 # Actualizaț i valoarea mică dacă valoarea medie < element (în secunda

jumătate).
10. altfel:
11. înalte = mediu # Altfel, actualizaț i valoarea mare (elem în prima ha
lf).
12. returnlow Returnează poziț ia elementului
13. căutăm.

Este important camijlocș iînaltniciodată nu sunt egale. Acesta este un loc în care unele
dezvoltatorii fac greș eli atunci când codifică acest algoritm.

130
Trebuie să adăugăm1când actualizaț i valoarea scăzută deoarece dacălow == mid, vom încheia
într-o buclă infinită ș i aceasta este o veste proastă! Acesta este un alt loc unde
dezvoltatorii greș esc.

Având în vedere că căutarea binară are dezavantajele menț ionate mai sus, îț i recomand să o înveț i.
din memorie.

13.4 - Îmbunătăț irea jocului nostru de ghicit numere

Acum putem lua acest algoritm de căutare binară ș i să-l modificăm uș or pentru a se potrivi nevoilor noastre.

joc. O să adăugăm o verificare astfel încât să nu facem mai mult de 20 de iteraț ii din
algoritmul de căutare binară adică împarte lista de mai mult de 20 de ori.

[Link] la random importă randint


2.
[Link] = [xforxinrange(0, 100000)]
[Link] = randint(0, len(arr))
5.
6.
[Link] = 0
8.înalt = len(arr)
9.i = 0
10.câtă vreme low < high ș i i < 20:
11. mid = (low + high) // 2
12.
13. daca ifarr[mid] < secret:
14. jos = mijloc + 1
15. altfel:
16. înalt = mediu
17. i += 1
18.
[Link] < 20:
20. print("Numărul secret este " + str(low))
21. altfel:
22. Noroc rău, nu ai ghicit numărul secret

Versiunea noastră îmbunătăț ită a jocului va ghici (găsi) numărul secret în cadrul
20 încercări de fiecare dată.

This is important because we get guess the answer correctly, in the worst case,
în 20 de încercări, în timp ce abordările noastre anterioare, cel mai rău caz ar fi avut
au fost 100.000 de încercări!

13.5 Analiza căutării binare


În această secț iune voi examina complexitatea timpului de execuț ie a căutării binare.
aș a cum am făcut cu Sortarea prin Inserț ie ș i Sortarea prin Selecț ie.

Sortarea prin inserț ie ș i sortarea prin selecț ie aveau o complexitate de timp de:

131
O(n)2

Căutarea binară are o complexitate de timp de:

O(log(n))

Mai specific:

O(log2n)

Este puț in mai complicat să se spună care este timpul de execuț ie al unui algoritm ca acesta. Aș a cum o
o regulă generală, dacă împărț im intrarea la jumătate la fiecare iteraț ie, atunci va
are un timp de execuț ie logaritmic (sau cel puț in, un component logaritmic în timpul său de execuț ie
complexitate).

Amintiț i-vă graficul Sortării prin Inserț ie ș i al unui algoritm O(n). Iată graficul
a complexităț ii de timp a unui algoritm cu căutare binară.

Poț i observa clar că, pe măsură ce intrarea devine mult mai mare, timpul necesar pentru...
algoritmul pentru completare începe să se stabilizeze ș i creș terea dimensiunii intrării începe
a avea un efect din ce în ce mai mic asupra performanț ei algoritmului.

132
Complexitatea spaț ială a căutării binare este de asemenea O(1), ceea ce înseamnă memorie constantă, deoarece noi

don't create any copies of the list when searching.


Acesta este considerat un algoritm foarte eficient, deoarece complexitatea sa de timp este apropiată
complexitatea temporala este constantă ș i complexitatea spaț ială este constantă.

13.6 - Exerciț ii
Întrebarea 1
Răspunde la următoarele întrebări:

• De ce trebuie să adăugăm 1 lalow când îș i actualizează valoarea?


• Care este complexitatea de rulare a căutării binare
• Care este complexitatea spaț ială a căutării binare?

Întrebarea 2
Folosind ceea ce ai învăț at în acest capitol, scrie o funcț ie numităinsera()acela
utilizează un algoritm eficient (indiciu, indiciu...) ș i primeș te o listă ș i un element ca
introduce ș i returnează indexul la care acel element ar trebui să fie inserat în
listă.
De exemplu, apelarea funcț iei de inserare aș a cum este ar trebui să returneze următoarele:

[Link] ț i([1, 3, 4, 5], 2)


2.
3.# ÎNTORCERI
4.1 adică 2 ar trebui să fie inserat la indexul 1

Întrebarea 3
Din nou, folosind ceea ce ai învăț at, scrie o funcț ie numităcontine()asta durează
două argumente, o listă ș i un element ș i returnează dacă acel element
este inclus în acea listă.

De exemplu:
contains([1, 3, 5, 7], 3)

# RETURNĂRI
Adevărat
------------------------------

133
conț ine([1, 3, 5, 7], 2)

#RETURURI
Fals

134
Capitolul 14 - Tratarea erorilor
14.1 - Ridicarea Excepț iilor
În Python vei întâlni multe tipuri de erori ș i sunt sigur că te-ai confruntat cu
suficient până acum!

Am văzut erori de sintaxă care apar din cauza sintaxei incorecte, de exemplu, prea multe
paranteze de închidere. Vei întâlni ș i ceva numit erori de excepț ie.
Erorile de excepț ie apar ori de câte ori un cod Python sintactic corect generează o
eroare. Există multe tipuri de erori de excepț ie, pentru a numi câteva, vei primi
unImportErrorcând încerci să imporț i un modul care nu poate fi găsit, vei
obț ine unZeroDivisionErrorcând al doilea operand al împărț irii sau al modulului
operatorul este zero. Dacă întâlneș ti o eroare care nu se încadrează într-o specifică
categoria de excepț ie, Python va arunca oRuntimeError.

Uneori în programele noastre dorim să ridicăm o excepț ie dacă un anumit


această condiț ie apare. Această condiț ie ar putea să nu fie una care va prăbuș i programul nostru,
dar noi ca programatori nu vrem să se întâmple.

Pentru a ridica o excepț ie, folosimridicadeclaraț ie. Condiț ia în care ne aflăm


ridicarea excepț iei poate fi una care este ilogică. De exemplu, putem...
avem un program care schimbă viteza unei maș ini. Ar fi ilogic pentru ca nostru
maș ina să meargă cu o viteză negativă, deoarece nu există aș a ceva.

Am ridica excepț ia după cum urmează:

1.defdecrease_velocity(curr_vel, decrease):
2. returncurr_vel - decrease
3.
[Link]():
5. car_velocity = 20
6. inp = int(input())
7. whileinp:
8. car_velocity = decrease_velocity(car_velocity, inp)
9. dacă_viteza_masinii < 0:
10. ridicaExceptie("Maș ina nu poate avea o viteză negativă")
11. inp = int(input())
12.
[Link]ă__nume__=="__principal__":
[Link]()

Rulând acest lucru cu următoarele intrări, ar oferi următorul rezultat:


135
$ py schimbă_viteza.py

5
6
7
5
Eroare de urmărire (ultima apelare cea mai recentă):

Fiș ierul "[Link]", linia 14, în <modul>

funcț ia principală()
Fiș ier "[Link]", linia 10, în main

ridica Excepț ie("Maș ina nu poate avea o viteză negativă")

Excepț ie: Maș ina nu poate avea o viteză negativă

Aș a cum poț i vedea, am ridicat o excepț ie cu propriul nostru mesaj de eroare personalizat.

Putem chiar să ridicăm tipuri specifice de excepț ii. UnEroaredevaloarepoate fi potrivit pentru
acest exemplu ș i pur ș i simplu înlocuimExcepț ie cuValueError.

De asemenea, putem ridica excepț ii atunci când ne aș teptăm ca erorile să apară aș a cum
în mod normal am face. Am ridica o excepț ie în acest caz pentru a oferi o mai bună
mesaj de eroare detaliat.

Dar, ca o regulă generală, se ridică o excepț ie atunci când un fundament


presupoziț ia codului actual s-a dovedit a fi falsă.

14.2 - Afirmatii
Dacă îț i aduci aminte de începutul acestei cărț i, am vorbit despre pre ș i
condiț ii post. O condiț ie prealabilă este o condiț ie care este întotdeauna adevărată înainte de
executarea unor coduri. Condiț iile prealabile pot fi utilizate în funcț ii pentru
aplicarea unui contract între o funcț ie ș i invocatorul său. Să presupunem că avem
o funcț ie care necesită o listă ca argument. Vrem să afirmăm că
argumentul trecut funcț iei este o listă ș i nu altceva, cum ar fi un ș ir.

Implementăm aserț iuni în python folosindafirma

[Link](arr):
2. assert(type(arr) == list)
3. # Faceț i sortarea
4.
[Link]():
6.
7. arr = [6, 3, 5, 1, 8]

136
8. sortator(arr)
9.
10. Am ajuns până aici
11.
12. arr ="Hello"
13. sortator(arr)
14.
[Link]ă__nume__=="__principal__":
[Link]()

rularea codului de mai sus produce următoarea ieș ire:


$ py [Link]
Am ajuns până aici
Urma de apel (cel mai recent apel a fost):

Fiș ierul "[Link]", linia 16, în <modul>

principala()
Fiș ierul "[Link]", linia 13, în main

ordonator(arr)
Fiș ier "[Link]", linia 2, în sorter

assert(type(arr) == list)

Eroare de aserț iune

După cum poț i vedea, afirmaț ia noastră a fostAdevăratcând am trecut lista, aș a că programul
a continuat ca de obicei. Când am trecut un ș ir de caractere funcț iei de sortare,
afirmaț ie returnatăFalsiar programul nostru s-a încheiat ș i a generat unEroare de aserț iune.

14.3 - încearcă & except

În această secț iune voi vorbi despre gestionarea excepț iilor pe care le putem întâlni.
întâmpinare în codul nostru. În Python, pentru a gestiona excepț iile, folosim
aîncercăș icu excepț iabloc. Capturăm erorile folosind aceste construcț ii.

Caleaîncearcăș iexceptlucrările de blocuri nu sunt atât de diferite de


undacăș ialtcevadeclaraț ie. În interiorulîncearcăbloc în care punem codul care ar trebui să ruleze ca
"normal". Dacă se ridică o excepț ie înîncearcăblochează, apoi capturăm asta
excepț ie încu excepț iabloc. Prin interceptarea excepț iei, putem gestiona
eroare fără ca programul nostru să se blocheze.

Permite-mi să dau două exemple. Unul în care nu încercăm să prindem excepț ia ș i


una unde facem.

[Link] = input()
2. cu deschiderea (filename) ca f:

137
3. lines = [Link]()
4.
[Link](liniile)

Aceasta ar produce următoarea eroare:


$ py citeste_fisier.py

Urme de apel (cea mai recentă apelare a avut loc ultima dată):

Fiș ierul "[Link]", linia 1, în <modul>

cu open("[Link]") ca f:

FileNotFoundError: [Errno 2] No such file or directory: '[Link]'

Programul nostru s-a prăbuș it. Ce ar fi dacă am dori să gestionăm acest lucru în mod corespunzător ș i

Permiteț i utilizatorului să introducă din nou numele fiș ierului? Folosim unîncearcăș iexceptblochează la
fă asta.

[Link] = input("Enter a file name: ")


2.în timp ce numele fi ș ierului:

3. încercă:
4. cu deschiderea(filename) ca f:
5. print([Link]())
6. filename = input("Enter a file name: ")
7. exceptFileNotFoundError:
8. Fiș ierul respectiv nu există în directorul curent
9. filename = input("Enter a file name: ")

Acum, dacă rulăm codul nostru:

$ py citeste_fisiere.py

Introduceț i un nume de fiș ier: [Link]

Acel fiș ier nu există în directorul curent


Introduceț i un nume de fiș ier: [Link]

['This is line one.\n', "I'm line two.\n", "And I'm line three"]
Introduceț i un nume de fiș ier: [Link]

Acest fiș ier nu există în directorul curent

Putem vedea, mai degrabă decât ca programul nostru să se blocheze, gestionăm

theFileNotFoundError într-un mod corect ș i permite utilizatorului să reintroducă un


numele_fisierului.
Python are o ierarhie de excepț ii. Aceasta este prezentată mai jos:

BaseException
+-- SystemExit
+-- Interrupere Tastatură

138
+-- GeneratorExit
+-- Excepț ie
+-- StopIteration
+-- Opreș teAsyncIteraț ia
+-- EroareAritmetica
| +-- EroarePunctFloat
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- Eroare de buffer

+-- EOFError
+-- ImportError
| +-- Eroare: Modul netăcut
+-- LookupError
| +-- Eroare de index

+-- KeyError
+-- Eroare de memorie

+-- NameError
+-- UnboundLocalError
+-- Eroare de tip OSError

| +-- BlockingIOError
| +-- EroareProcesCopil
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- Eroare: Fi ș ierul nu a fost găsit

| +-- Eroare întreruptă


| +-- Este o eroare de tip IsADirectoryError

139
| +-- EroareNuEsteDirector
| +-- EroareDePermisiune

| +-- EroareCautareProces
| +-- Eroare de Timeout

+-- Eroare de referinț ă

+-- RuntimeError
| +-- NotImplementedError
| +-- Eroare de recursie

+-- Eroare de sintaxă

| +-- Eroare de indentare

| +-- Eroare de tabulare

+-- Eroare de sistem

+-- TypeError
+-- Eroare de valoare

| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Atenț ie
+-- Avertizare de deprecatie

+-- Avertisment de deprecere în aș teptare

+-- Avertisment de rulare

+-- Avertizare de sintaxă

+-- AvertizareUtilizator

+-- Avertizare de viitor

+-- Avertisment de import

+-- Avertisment Unicode

+-- AvertismentBytes

+-- Avertizare de resurse

Am fost destul de specifici cu excepț ia noastră în exemplul precedent.


Presupunem că o altă eroare ar putea apărea undeva în programul nostru ș i suntem
nesigur în legătură cu ceea ce ar putea fi, dar vrem totuș i să permitem utilizatorului să introducă un

140
numele fiș ierului după ce se întâmplă. Putem avea mai multe clauze except după
thetrybloc.

[Link] = input("Enter a file name: ")


2.în timp ce numele fi ș ierului:

3. încearcă:
4. cu open(filename) ca f:
5. print([Link]())
6. filename = input("Enter a file name: ")
7. exceptFileNotFoundError:
8. Fiș ierul respectiv nu există în directorul curent
9. filename = input("Enter a file name: ")
10. cu excepț ia:
11. A apărut o eroare neaș teptată
12. filename = input("Enter a file name: ")

Acum, dacă ne confruntăm cu o altă eroare, am gestionat-o cu o abordare mai generală


excepț ie.
De asemenea, gestionăm excepț iile pe care le ridicăm explicit în acelaș i mod:

[Link] = int(input())
2.încercare:

3. dacă inp < 5:


4. raiseValueError
5. altfel:
6. tipăreș te(inp)
[Link]:
8. Inputul nu ar trebui să fie mai mic de 5

14.4 - în sfârș it

De obicei, dacă avem unîncearcăș iînafarădebloc, vom încerca să facem ceva specific
care poate fi predispus la erori. În exemplul din secț iunea anterioară, că
ceva specific deschidea un fiș ier. Nu ar trebui să cerem utilizatorului pentru
introduceț i din nou înîncearcăbloc. De asemenea, nu ar trebui să cerem utilizatorului să introducă
numele fiș ierului din nou după ce am gestionat excepț ia încuexcepț ia bloc.

În schimb, vrem o modalitate de a curăț a după aceea. În Python, facem acest lucru
cuînsfârș it declaraț ie.
Acest lucru este demonstrat mai jos:

[Link] = input("Enter a file name: ")


2.în timp ce numele fi ș ierului:

3. încearcă:
4. cu open(filename) ca f:
5. print(f.citeste_liniile())
6. exceptFileNotFoundError:
7. Fiș ierul respectiv nu există în directorul curent
8. cu excepț ia:
9. A apărut o eroare neaș teptată
10. în sfârș it

141
11. filename = input("Enter a file name: ")

Theînceledinurmăblocul este întotdeauna executat chiar dacă nu au fost ridicate excepț ii în


theîncearcăblocaț i. Deș i codul nostru este predispus la erori din input-ul utilizatorului, noi
poate gestiona asta corect, făcând astfel codul nostru mai robust.

14.5 - Exerciț ii
Întrebare 1
Scrie un program care ia un număr dintr-un argument de linie de comandă ș i
afiș ează multiplii acelui număr până la 10. Utilizatorul ar trebui să poată de asemenea
pentru a specifica un flag de formatare ș i/sau un flag de scurtare la linia de comandă. Ca un
exemplu, aruncă o privire la câteva moduri diferite în care un utilizator ar putea să ruleze

program:
$ py times_tables.py 15
0 * 15 = 0
1 * 15 = 15
2 * 15 = 30
3 * 15 = 45
4 * 15 = 60
5 * 15 = 75
6 * 15 = 90
7 * 15 = 105
8 * 15 = 120
9 * 15 = 135
10 * 15 = 150

$ py times_tables.py -f 15
0 * 15 = 0
1 * 15 = 15
2 * 15 = 30
3 * 15 = 45
4 * 15 = 60
5 * 15 = 75

142
6 * 15 = 90
7 * 15 = 105
8 * 15 = 120
9 * 15 = 135
10 * 15 = 150

$ py times_tables.py -f -s 15
0
15
30
45
60
75
90
105
120
135
150

În al doilea exemplu, observaț i-fsteag ș i, -ssteag în al treilea exemplu.


Programul tău ar trebui să fie capabil să gestioneze următoarele situaț ii care pot provoca
exceptions:

• Utilizatorul introduce o steag care nu există de exemplu-d


• Utilizatorul introduce un steag, dar nu un număr
• Utilizatorul nu introduce niciun argument de linie de comandă
• Utilizatorul nu introduce un număr, în schimb introduce un ș ir de caractere ("salut" pentru

exemplu)
• Utilizatorul introduce aceeaș i steag de două sau mai multe ori.
• Utilizatorul introduce două sau mai multe numere

Acest program poate dura ceva timp pentru a fi implementat.

Întrebarea 2
Când ar trebui să folosim următoarele?

143
• a ridica
• în cele din urmă
• încearcăș iexcepț ie
• Ce este o precondiț ie?
• Ce este o postcondiț ie?

144
Capitolul 15 - Mai multe despre tipurile de date

15.1 - Tuple
O tuplă este în esenț ă o listă imutabilă. Tuplele, la fel ca ș irurile, nu pot fi modificate.
după creare. Cu toate acestea, un tuplu este diferit de un ș ir de caractere în sensul că, în timp ce ș irurile

consistă exclusiv din caractere, un tuplu poate conț ine obiecte de orice tip (ca o listă).

Pentru a crea un tuplu, folosim operatorul virgulă:

>>> prietena_mea=2, 4, 8, 16
>>> tupla_mea
(2, 4, 8, 16)

În general, încapsulăm un tuplu între paranteze, deoarece asta face lucrurile mai uș oare.
citiț i.
>>> tupla_mea= Bună
>>> tupla_mea
"Bună ziua"

Pentru a crea un tuplu cu o singură valoare, trebuie să includeț i o virgulă!

>>> t= (4,)
>>>tip(t)
<clasa'tuplu'>
>>> v= (4)
>>>tip(v)

<clasă'int'>

Putem concatena tuple folosind+ operator ș i repetă tuplurile folosind


the* operator:
>>> t= (2, 4, 6, 8)
>>> u= (1, 3, 5, 7)
>>> t+ u
(2, 4, 6, 8, 1, 3, 5, 7)
>>> t*2

(2, 4, 6, 8, 2, 4, 6, 8)

145
De asemenea, putem tăia ș i indexa în acelaș i mod în care o facem cu ș irurile de caractere:

>>> t= (5, 4, 3, 2, 1)
>>> t[3]
2
>>> t[::-1]
(1, 2, 3, 4, 5)
>>> t[1:3]
(4, 3)

De asemenea, putem itera peste tupluri folosind bucle. O să folosescpentruloop aici,


dar poț i folosiîntimpceprea
>>> caractere= ("a","b","c")
>>>pentrucînchars:

...printează(c)

...
a
b
c

We can use the înoperator pentru a verifica dacă o valoare există într-un tuplu
>>> t= ("John","Liam","Tony")
>>>print"Tony"int
Adevărat

Ș i în cele din urmă, aș a cum era de aș teptat, primim o eroare dacă încercăm să schimbăm conț inutul unui tuplu:

>>> t= (1, 2, 3)
>>> t[0] =4
Urmează (cea mai recentă apelare ultimei):

Fiș ier "<stdin>", linie1, în <modul>


TypeError: obiectul 'tuple' nu facenualocarea articolelor de suport

Dacă îț i aminteș ti capitolul despre dicț ionare,[Link]()metodă


returnează o listă de tuple.

>>> d= {"a":10,"b":11,"c":12}
pentru(k, v) î[Link]():

146
...print(k, v)
...
a10
b11

c12

15.2 - Seturi
Un set este o colecț ie de obiecte de tip arbitrar. Obiectele setului se numesc
membrii săi. Seturile sunt un tip neordonat (ca dicț ionarele). Ele sunt de asemenea
iterabile. O caracteristică importantă a mulț imilor este că acestea conț in doar o singură copie a unei
un obiect particular adică duplicatele nu sunt permise. Seturile sunt tipuri mutabile.

Seturile sunt folosite în general pentru testarea apartenenț ei ș i eliminarea duplicatelor. Ele
de obicei deț in o colecț ie de obiecte similare.

Pentru a profita din plin de seturi, va trebui să aveț i o bună înț elegere a setului
teorie. Nu voi acoperi teoria mulț imilor în această carte, aș a că poț i să te documentezi despre ea.

aici:Introducere în teoria mulț imilor. Cu toate acestea, este posibil să fii familiarizat cu setul de bază
teoria aș a cum ai acoperit-o la ș coală. Mulț imile sunt foarte importante ș i sunt unul dintre
tipuri de date care apar în interviuri.

În Python, un set este creat folosindset()funcț ie.


x=set()# s este acum un set gol

De asemenea, putem crea un set folosind valori separate prin virgulă, închise între acolade.

braces:
x= {1, 2, 3, 4}

Reț ineț i că nu putem folosi{} pentru a crea un set gol, deoarece acest lucru ar crea un
dicț ionar gol.

Folosimînoperator pentru a verifica apartenenț a:


>>> x= {2, 4, 6, 8}
6inx
Adevărat

Când folosimînoperator pe ș iruri de caractere ș i liste, complexitatea timpului de execuț ie este


O(n). Când folosim acest operator pe seturi, în medie este O(1). Acesta este acelaș i
cu dicț ionare. Prin urmare, este foarte rapid de accesat.

147
Pentru a adăuga un nou membru la un set, folosimadauga()method:

>>> x= {2, 4, 6}
>>> [Link]ă(8)
>>> x

{8, 2, 4, 6}

Observaț i cum setul nu are o ordine.

Putem obț ine lungimea unui set folosindlen()funcț ie:


>>> x= {2, 4, 6}
>>>lungime(x)

De asemenea, putem crea un set din alte obiecte:

>>> s=setabcdefghijk
>>> s
{'d','e','i','h','k','g','j','f','a','b','c'}

>>> x=set([2, 4, 6, 8])


>>> x
{8, 2, 4, 6}

Aminteș te-ț i: Duplicatele sunt eliminate din seturi!

>>> lista_mea= [2, 2, 6, 4, 5, 4, 4, 9]


>>> setul meu=set(lista_mea)
>>> setul meu

{9, 2, 4, 5, 6}

Aceasta este deosebit de utilă atunci când căutăm elemente unice în ceva.

Putem obț ine intersecț ia a două mulț imi A ș i B folosind


theintersecț ie() metodă. Aceasta va returna un set care conț ine elementele
care sunt comune atât pentru A, cât ș i pentru B:

>>> A= {2, 3, 4, 5, 6, 7}
>>> B= {4, 5, 6, 10, 34, 22, 1}
>>> [Link](B)
{4, 5, 6}

148
Putem obț ine uniunea a două mulț imi A ș i B folosinduniune()metodă. The
uniunea a două mulț imi este mulț imea elementelor din A ș i B:
>>> A= {1, 3, 3, 7}
>>> B= {2, 3, 6, 8}
>>> [Link](B)
{1, 2, 3, 6, 7, 8}

We can get the set difference between two sets A and B using
thediferenț ă() metoda. Diferenț a mulț imii A faț ă de B este mulț imea elementelor din A dar
nu în B. La fel, diferenț a de seturi B faț ă de A este setul de elemente din B, dar nu din A:

>>> A= {1, 2, 3, 4, 5, 6}
>>> B= {4, 5, 6, 7, 8, 9}
>>> [Link]ț ă(B)
{1, 2, 3}
>>> [Link]ț ă(A)
{8, 9, 7}

De asemenea, putem verifica dacă mulț imea B este o submulț ime a lui A utilizândissubset()metodă. Set A
A este un subsistem al setului B dacă fiecare membru al lui A este, de asemenea, un membru al lui B:

>>> A= {2, 4, 6}
>>> B= {1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> A.este_submultime(B)
Adevărat
>>> B.este_submulț ime(A)
Fals

Putem verifica dacă A este un supermultime a lui B folosindissuperset()metodă. B este o


superset al A dacă fiecare membru al A este de asemenea un membru al B:

>>> A= {2, 4, 6}
>>> B= {1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> B.este_supraconjunctie(A)
Adevărat
>>> A.este_superior(B)
Fals

149
15.3 - Liste ș i comprehensiuni de liste

Am văzut cum să creaț i liste ș i ar trebui să fii obiș nuit să o faci la acest
punct. Cu toate acestea, consideraț i următoarea sarcină:

Scrie un program care construieș te o listă ce conț ine toate numerele paire din a
a doua listă.
Sarcina de a construi o listă prin procesarea elementelor dintr-o altă listă este foarte
task comun în informatică. Până acum, a trebuit să folosim un anumit tip de buclă
pentru a itera peste toate elementele din a doua listă ș i a selecta numerele pare
Numerele. Python a oferit un scurtcircuit pentru asta numit comprehensiune de listă.
Ai văzut cum folosesc o compunere de liste într-un capitol anterior pentru a construi un
lista de 1.000 de întregi.

În această secț iune vom examina cum să creăm comprehensii de listă.


O compunere a listelor este o scurtătură pentru a construi o listă dintr-o alta.

Sintaxa pentru o compunere a unei liste este:[expresie pentru-clauză condiț ie].

De exemplu, pentru a crea o listă care conț ine fiecare număr de la 0 la 1.000, noi
a putea folosi următoarea compunere a listei:
lst= [xpentruxinrange(0,1000)]

Lista de mai sus se citeș te: "Adaugă x la noua listă pentru fiecare x din listă"
elementelor de la 0 la 1000.
Pentru a rezolva sarcina, am menț ionat la începutul acestei secț iuni că am putea folosi
următoarea compunere a listei:
>>> lista_mea= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> evenimente= [xpentruxînlista_meadacă nux%2]
>>> pare
[2, 4, 6, 8, 10, 12, 14]

În comprirea de mai sus,xeste expresia,pentru x în my_lsteste pentru-


clauză ș idacă nu x % 2aceasta este condiț ia. Ea se citeș te astfel: "Adaugă x la noul"
lista pentru fiecare x din my_lst dacă x modul 2 nu este egal cu 0.

Amintiț i-vă, 0 este fals, prin urmare,dacă nu x % 2este adevărat dacă x % 2 este egal cu 0.

150
Putem folosi o expresie de listă pentru a construi o listă de valori pătrate din
o altă listă folosind următoarea compunere a listelor:
>>> vals= [1, 2, 3, 4, 5, 6]
>>> pătrate= [x**2forxînvals
>>> pătrate
[1, 4, 9, 16, 25, 36]

Să vedem o compunere de listă care va ridica la pătrat numerele pare ș i le va lăsa


orice numere impare sunt aceleaș i:

>>> vals= [1, 2, 3, 4, 5, 6, 7, 8]


>>> evens_squared = [x**2decatx %2elsexpentruxînvals
>>> evens_squared
[1, 4, 3, 16, 5, 36, 7, 64]

Lista de mai sus se citeș te astfel: "Adaugă pătratul lui x dacă x este par"
altfel doar x pentru fiecare x din vals
Compresiile de liste sunt atât de comune încât este uș or să te împiedici de ele ș i de multe ori le vei vedea.

sunt utilizate dacă cercetezi orice probleme online. În general, ele sunt o
constructor găsit doar în Python. Dacă treci la Java, de exemplu, în
în viitor, nu vei putea folosi comprimele de listă deoarece acestea nu există în
Java.
Comprehensiile nu se aplică doar listelor. Ele pot fi folosite ca scurtături pentru
creând o nouă colecț ie din alte colecț ii. Prin urmare, ne-am stabilit ș i
compresiuni de dicț ionar:
>>> setul meu= {xpentruxinrange(10)}
>>> setul_meu
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> my_dict= {x:Truepentruxîn intervalul (5)}
>>> my_dict
{0Adevărat,1Adevărat,2Adevărat,3Adevărat,4:Adevărat}

Exersează cu acestea! Foloseș te-le când poț i (ceea ce va fi probabil des).


Utilizarea compresiilor este modul pythonic de a scrie cod Python.

15.4 - Exerciț ii

151
Descărcaț i următorul fiș ier (copiaț i această pagină într-un fiș ier text):Dicț ionar.

Vei folosi aceasta pentru unele dintre exerciț ii.

Întrebarea 1
În timpul unui studiu, mai mulț i ingineri software au fost întrebaț i care sunt cele mai bune 3

cele mai iubite limbaje de programare erau.

Scrie un program care determină numărul de limbi unice date ca


răspunsuri în timpul studiului. Mai jos se află fiș ierul de intrare, iar fiecare linie fiind un răspuns

dat de un inginer software:


java python c++
python scala c
java haskell javascript
javascript python c
c c++ c#
c# haskell java

Programul dumneavoastră ar trebui să fie rulat astfel ș i să ofere următoarea ieș ire:

$ py [Link] [Link]
8

Întrebare 2
Scrie o compunere de listă care creează o listă conț inând toate numerele impare
între 0 ș i 10.000.

Întrebarea 3
Folosind dicț ionarul pe care l-ai descărcat anterior, scrie un program care construieș te o listă
care conț ine toate cuvintele care au 18 caractere sau mai mult. Tu
ar trebui să foloseș ti o comprehensiune de listă pentru a face asta!

Programul dvs. ar trebui să fie rulat astfel:

$ py long_words.py < dicț [Link]

Notă: Acest lucru poate dura ceva timp, deoarece fiș ierul de intrare este mare!

Întrebarea 4

152
Folosind dicț ionarul pe care l-ai descărcat anterior, scrie un program care construieș te o listă
conț inând toate cuvintele care conț in fiecare vocală (a, e, i, o ș i u). De exemplu,
the word "equation" should be in the list. You should make good use of a list
înț elegere pentru a face asta!

Programul dumneavoastră ar trebui rulat astfel:

$ py [Link] < [Link]

Întrebarea 5
Folosind dicț ionarul pe care l-ai descărcat anterior, scrie un program care construieș te o listă
conț inând toate cuvintele care conț in exact 4 a-uri ș i se termină în 'ian'. Pentru
exemplu, cuvântul "alabastrian" ar trebui să fie în listă. Ar trebui să faci bine
foloseș te o compunere a listelor pentru a face asta!

Programul dvs. ar trebui să fie rulat după cum urmează:

$ py two_conditions.py < [Link]

Întrebarea 6
Folosind dicț ionarul pe care l-ai descărcat anterior, scrie un program care construieș te o listă
conț inând toate cuvintele din dicț ionar a căror inversă apare de asemenea. Pentru
exemplu, cuvintele "lager" ș i "regal" ar trebui să fie în listă. Ar trebui să faci
utilizare bună a comprehensiunilor pentru a face asta!

Programul dvs. ar trebui să fie rulat astfel:

$ py [Link] < [Link]


Sugestie: Poate doriț i să vă gândiț i la soluț ia dumneavoastră pentru aceasta. Programul dumneavoastră poate...

va dura foarte mult timp să ruleze dacă nu implementaț i o soluț ie mai eficientă!

153
Capitolul 16 - Recursie ș i Quicksort
16.1 - Recursie
Înainte să continui, vreau să spun asta, scrierea unei soluț ii recursive este
DIFICIL când începem. Nu te aș tepta să funcț ioneze din prima. A scrie o
soluț ia recursivă implică o nouă modalitate de a gândi ș i poate fi de fapt
destul de descurajant pentru cei noi, dar rămâi cu el ș i te vei întreba cum ai ajuns
întotdeauna ai găsit-o atât de dificilă.

Deci, ce este, de fapt, recursia? O soluț ie recursivă este una în care soluț ia la
o problemă este exprimată ca o operaț iune asupra unei versiuni simplificate a aceleaș i
problemă.

Acum, probabil că asta nu a avut prea mult sens ș i este foarte complicat să
explică exact cum funcț ionează aș a că să luăm un exemplu simplu:

[Link](x):
2. returnreduce(x-1)

So,what’shappening here? We have a function called reduce which takes a


parametrux (un număr întreg) ș i vrem să-l reducem la '0'. Sună simplu aș a
să-l rulăm când trecem 5 ca parametru ș i să vedem ce se întâmplă:
reduce(5)
RuntimeError: adâncimea maximă a recursiei a fost depăș ită

O eroare? Ei bine, să ne uităm mai îndeaproape la ce se întâmplă aici:

reduce(5) apelează reduce(4) care apelează reduce(3)…….Astfel, iniț ialul nostru


apelul reduce(5) este primul apel dintr-un număr infinit de apeluri la reduce(). Fiecare
când se apelează funcț ia reduce(), Python instanț iază o structură de date pentru a o reprezenta
apel particular la funcț ie. Această structură de date se numeș te cadru de stivă. O
cadrele de stivă ocupă memorie. Programul nostru încearcă să creeze un infinit
numărul de cadre de stivă care ar necesita o cantitate infinită de memorie
pe care nu o avem, aș a că programul nostru se blochează.

Pentru a rezolva această problemă, trebuie să adăugăm ceva numit cazul de bază.
Aceasta este pur ș i simplu o verificare pe care o adăugăm astfel încât funcț ia noastră să ș tie când să înceteze apelurile

în sine. Cazul de bază este de obicei cea mai simplă versiune a problemei originale
ș i unul la care ș tim întotdeauna răspunsul.

154
Să corectăm eroarea noastră adăugând un caz de bază. Pentru această funcț ie, vrem să se oprească.
când ajungem la 0.

[Link](x):
2. dacă x == 0:
3. return0
4. returnreduce(x-1)

Aș a că acum, când rulăm programul nostru, obț inem:

reduce(5)
0

Groza, funcț ionează! Să aruncăm o altă privire asupra a ceea ce se întâmplă de data aceasta. Noi numim

reduce(5) care apelează reduce(4)... care apelează reduce(0). Ok, stop aici, avem
a lovit cazul nostru de bază. Acum, ceea ce va face funcț ia este să returneze 0 apelului anterior
de reduce(1) care returnează 0 la reduce(2).... care returnează 0 la reduce(5) care
îț i returnează răspunsul. Iată, prima ta soluț ie recursivă!

Să privim un exemplu mai practic. Să scriem o soluț ie recursivă pentru a găsi


N! (sau N factorial):

Factorialul N este definit ca: N! = N * (N-1) * (N-2)…… * 2 * 1.

De exemplu, 4! = 4 * 3 * 2 * 1
Cazul nostru de bază pentru acest exemplu este N = 0, deoarece 0! este definit ca 1. Aș adar, să scriem nostra

funcț ie:

[Link](n):
2. dacă n == 0:
3. return1
4. returnează * factorial(n-1)

Bine, să vedem asta în acț iune. Vom apela funcț ia noastră ș i vom trece 4 pentru n:

factorial(4) apelează factorial(3) ..... care apelează factorial(0) care este cazul nostru de bază
aș adar, întoarcem 1 înapoi la apelul anterior al factorial(1) care ia 1-ul nostru ș i
înmulț eș te-l cu 1, ceea ce evaluează la 1, care este întors la factorial(2)
care ia 1-ul nostru ș i îl înmulț eș te cu 2, ceea ce evaluează la 2, care îl pasează.
înapoi la factorial(3) care înmulț eș te 3 cu 2 pentru a obț ine 6, care o transmite înapoi la
factorial(4) care multiplică 4 6 care evaluează la 24 care este returnat ca al nostru
răspuns.

Acestea sunt cazuri foarte simple ș i nu foarte utile, dar a putea identifica când
o soluț ie recursivă poate fi implementată ș i apoi implementând acea soluț ie

155
este o abilitate care te va face un programator mai bun. Pentru anumite probleme
recursia poate oferi o soluț ie intuitivă, simplă ș i elegantă.

De exemplu, puteț i implementa o soluț ie recursivă pentru a găsi numărul de


noduri într-o structură de arbore, numără câte noduri frunză sunt într-un arbore sau chiar
returnaț i dacă un arbore de căutare binară este echilibrat AVL sau nu. Aceste soluț ii
tind să fie destul de scurte ș i elegante ș i să îndepărteze de la lungul proces iterativ
abordare pe care poate ai adoptat-o.
Aș a cum am spus, recursia nu este uș oară, dar rămâi la ea, va face clic ș i va părea atât de simplă.
te vei întreba cum ai găsit vreodată atât de dificil.

16.2 - Memorare
Am scris soluț ia la problema Fibonacci de câteva ori
pe parcursul acestei cărț i. Când am redactat acele soluț ii, am folosit o abordare iterativă
abordare. Totuș i, putem adopta o abordare recursivă. Poate fi dificil să
recognize when a recursive solution is an option, but this is a great example of
când o soluț ie recursivă este o opț iune!

Să vedem o soluț ie pentru următoarea problemă:


Scrie un program care primeș te un număr întregnș i calculează n-lea număr Fibonacci
number:

[Link](n):
2. dacă ifn <= 1:
3. return1
4. altceva:
5. returnfib(n-1) + fib(n-2)

Asta e mult mai simplu! În acest exemplu, vom lua fib(0) ca fiind 1 ș i fib(1) ca fiind 1.
de asemenea. Prin urmare, cazul nostru de bază este dacă n este 0 sau 1, returnăm 1. Cazul recursiv
provine direct din definiț ia secvenț ei Fibonacci, adică:
fib(n)=fib(n−1)+fib(n−2)
Cu toate acestea, este posibil să fi observat că, dacă introduceț i orice valoare mai mare decât

(aproximativ) 35 - 40 programul tău începe să încetinească cu adevărat ș i să ia o FOARTE


de mult timp ș i orice peste 45~50, ei bine... mergi să faci o ceaș că de cafea ș i
întoarce-te ș i ar putea fi terminat. Ce cauzează asta? Să ne uităm la un
diagramă a primelor câteva apeluri recursive lafib().

156
Putem observa că atunci când apelămfib(5) noi, în diverse momente în funcț iile noastre
execution, call fib(1)de 5 ori! ș ifib(2)De 3 ori! Acesta este inutil. De ce
trebuie să recalculăm valoarea pentrufib(1)iar ș i iar?

Putem reduce numărul de ori în care trebuie să calculăm diverse valori prin
folosind o tehnică numită memoizare. Memoizarea este
o tehnică de optimizare utilizată pentru a accelera programele noastre prin stocarea în cache
rezultatele apelurilor funcț iilor costisitoare. Un cache este, în esenț ă, o stocare temporară
zona ș i putem implementa un cache înfib()funcț ie pentru a stoca anterior
valori calculate ș i doar le extragem din cache când este nevoie în loc să
efectuarea apelurilor de funcț ie inutile.

Putem folosi un dicț ionar pentru a implementa un cache. Aceasta ne va oferi O(1) pentru
accesarea ș i va îmbunătăț i drastic performanț a funcț iei noastre.

Să vedem cum se face asta:

[Link](n, cache=None):
2. Evita capcana argumentului mutabil implicit!
3. ifcache == None:
4. cache = {}
5. # Caz de bază
6. daca n <= 1:
7. return1
8. Dacă valoarea nu este în cache, atunci calculează-o ș i stocheaz-o în cache
9. elif nu este în cache:
10. cache[n] = fib(n-1, cache) + fib(n-2, cache)
11. Returnează valoarea
12. returncache[n]

157
Acum putem sunafib(900)ș i obț ineț i răspunsul imediat! Implicit, Python
limitează adâncimea recursivităț ii la 1000. Putem suprascrie acest lucru, dar de obicei nu este o
idee bună!

Să ne uităm acum la copacul nostru, de data aceasta pentrufib(6).

Putem vedea din arbore că sunt mai puț ine apeluri către funcț ie, chiar dacă
suntem o valoare mai mare. Aceasta este o creș tere semnificativă a performanț ei. Chiar ș i apelând
de lafib(5)ne-am salvat 6 apeluri de funcț ii!

16.3 - Quicksort partea 1


În secț iunile următoare, voi analiza o sortare foarte importantă.
algoritm: sortare rapidă. Sortarea rapidă este un algoritm de sortare recursiv care utilizează
o strategie de tip divide ș i cucereș te. Built-in-ul Pythonordonat()funcț ia foloseș te un
algoritm Quicksort modificat. Împărț ire ș i cucerire este o metodă de rezolvare a problemelor

strategia în care continuu să descompun o problemă în părț i mai uș oare, mai...


subprobleme gestionabile ș i le rezolvăm.
În această secț iune, vom analiza sortarea listelor de numere.

Deoarece acesta este un algoritm de împărț ire ș i cucerire, dorim să luăm o listă de nesortate
numere întregi ș i împărț iț i problema în două probleme mai uș oare ș i apoi descompuneț i
fiecare dintre aceș tia în jos…. ș i aș a mai departe.

Pentru a realiza acest lucru, voi începe prin a explica operaț ia principală a quicksort-ului: partiț ionarea. Aceasta funcț ionează

după cum urmează:

>>> A= [6, 3, 17, 11, 4, 44, 76, 23, 12, 30]


>>> partiț ie(A,0len(A)-1)
>>>print(A)

158
[6, 3, 17, 11, 4, 23, 12, 30, 76, 44]

Deci, ce s-a întâmplat aici ș i cum funcț ionează? Trebuie să alegem câteva
numărul ca pivot. Funcț ia noastră de partiț ie primeș te 3 argumente, lista,
primul element din listă ș i pivotul. Ce încercăm să realizăm aici este
când partitionăm lista, tot ce este la stânga pivotului este mai mic decât
pivotul ș i tot ce este la dreapta este mai mare decât pivotul. Pentru prima
partiț ia văzută mai sus, 30 este pivotul nostru. Întotdeauna ne vom lua partiț ia să fie
ultimul element din listă. După partiț ionare, observăm că unele elemente s-au schimbat
poziț ie, dar tot ce este la stânga lui 30 este mai puț in decât acesta ș i tot ce este la
dreapta este mai mare decât ea.

Deci, ce înseamnă asta pentru noi? Ei bine, înseamnă că 30 este acum în


poziț ia sa corectă în listă Ș I acum avem două liste mai uș or de sortat. Toate
aceasta se face în loc, aș a că nu creăm liste noi.

Să ne uităm la cod:

[Link](A, p, r):
2. q=j=p
3. whilej < r:
4. dacă A[j] <= A[r]:
5. A[q], A[j] = A[j], A[q]
6. q += 1
7. j += 1
8. A[q], A[r] = A[r], A[q]
9. întoarce

Ceareturnqla final nu este necesar pentru partajul nostru, dar este esenț ial pentru
sortarea întregii liste. Codul de mai sus parcurge listaAș i
menț ine indiciip, q, j, r.

peste fixat ș i este primul element din listă.reste pivotul ș i este ultimul
element în listă. Elemente în intervalA[p:q-1]sunt cunoscuț i a fi mai puț in decât
sau egal cu pivotul ș i totul de laA[q-1:r-1]sunt mai mari decât
pivot. Singurele indici care se schimbă suntq ș ijLa fiecare pas noi
comparaA[j]cuA[r]Dacă este mai mare decât pivotul, se află în corect
poziț ie, aș a că incrementămjș i treceț i la următorul element. DacăA[j]este mai puț in
decâtA[r]noi schimbămA[q]cuA[j]După acest schimb, incrementămqastfel
extinderea gamei de elemente cunoscute ca fiind mai mici sau egale cu pivotul.
De asemenea, creș temj pentru a trece la următorul element care trebuie procesat.

Te încurajez să lucrezi printr-un exemplu cu o listă mică pe hârtie pentru a


fă acest lucru mai clar.

159
16.4 - Quicksort partea 2
Acum ne îndreptăm spre partea de quicksort. Amintiț i-vă că este un algoritm recursiv, aș a că va
apelează continuu lapartiț ionaț i() până când nu mai rămâne nimic de împărț it ș i tot
elementele sunt în poziț iile lor corecte. După prima partiț ie, noi
apelpartiț ionare()din nou, de data aceasta o numim pe lista elementelor din stânga lui
pivotul ș i lista de elemente la dreapta pivotului.

Să ne uităm la cod:

[Link](A, p, r):
2. ifr <= p: # Dacă r <= p, atunci lista noastră este sortată
3. returnare
4. q = împărț ire(A, p, r) partiț ionează lista de intrare
5. quicksort(A, p, q-1) apelează din nou quicksort pe tot ce este la stânga pivotului
6. quicksort(A, q+1, r) apelează din nou quicksort pe tot ceea ce este la dreapta pivotului
7. returnA

Este atât de simplu. Tot ce facem aici este să verificăm dacă indexul pivotului este mai mic decât sau
egal cu indexul începutului listei noastre pe care dorim să o partitionăm. Dacă este aș a, returnăm
deoarece orice listă a fost trecută nu mai trebuie să fie partitionată mai departe.

Altfel, împărț im lista A ș i apelăm din nou quicksort pe cele două noi sub
liste.
Pe linia 3, ne întoarcem fără a specifica nimic de întors. Aceasta se datorează faptului că.
funcț ia quicksort este o procedură.
Quicksort funcț ionează cel mai bine pe liste mari care sunt complet amestecate. Are cu adevărat
performanț ă slabă pe liste care sunt aproape sortate. Sau în notaț ia Big-O, cea mai bună
cazul (amestecat) este O(n log(n)) ș i în cel mai rău caz, (aproape sau complet
lista ordonată) este O(n^2).

Din nou, te încurajez să încerci asta pe hârtie cu o listă simplă. Te va ajuta să clarifici
ce se întâmplă.

16.5 - Exerciț ii
Important: These exercises are quite difficult! Make use of problem-solving
tehnici pentru a te ajuta să ajungi la o soluț ie. Schiț ând ce se întâmplă pe
hârtie, este o modalitate bună de a te ajuta!

160
Unele dintre aceste întrebări sunt genul de întrebări pe care le poț i aș tepta dacă obț ii un
întrebare de recursie când intervievăm la companii precum Google, Facebook
sau Amazon.

Întrebare 1
Ce este:

• Recursie?
• Memoizarea?

Întrebarea 2
Scrie o funcț ie recursivă care adună toate numerele de la 1 la 100.

Întrebarea 3
Scrieț i o funcț ie recursivă care primeș te un întreg ca argument ș i returnează
dacă acel întreg este o putere a lui 2. Funcț ia ta ar trebui să returnezeAdevăratsauFals

Întrebarea 4
Scrie o funcț ie recursivă care ia un ș ir de caractere ca argument ș i returnează
dacă acea sirgă este un palindrom. Funcț ia ta ar trebui să returnezeAdevăratsauFals.

Întrebare 5
Scrie o funcț ie recursivă care ia o listă de întregi ca argument ș i
returnează maximul acelei liste.

Sugestie: Gândindu-ne recursiv, maximul este fie primul element al listei sau
maximul listei rămase!

161
Capitolul 17 - Programare Orientată pe Obiect

Programare (OOP)
17.1 - Clase ș i Obiecte
Până acum, am întâlnit multe dintre tipurile încorporate ale Pythonului, cum ar fi

ca booleans, întregi, dicț ionare s.a.m.d. Acestea sunt toate tipuri de clasă. Asta înseamnă
că orice instanț ă a unui ș ir, listă, număr float etc. este un obiect al clasei ș ir, listă sau
float. Cu alte cuvinte, fiecare obiect de tip string, de exempluBună, este un exemplu de
clasa de ș iruri. Un obiect este o implementare a unui tip

În acest capitol, vom analiza un paradigme de programare numită obiect-


programare orientată pe obiecte (OOP). Acest paradigme se bazează pe conceptul
obiecte, care conț in date, sub formă de atribute ș i funcț ii (numite
metode).
În OOP, programele sunt concepute prin crearea lor din obiecte care interacț ionează
unii cu alț ii. O caracteristică importantă a obiectelor este că ele îș i folosesc
methods to access and modify their attributes. For example, if we wanted to
model aPersoană, ar putea avea unvârstăatribute ș i unnumeatribut. Fiecare
anul în care devin cu un an mai în vârstă, aș a că ar putea avea unschimba_varsta()metodă pentru

actualizaț i-vă vârsta.

Sintaxa generală pentru invocarea unei metode a unui obiect


estenumele_obiectului.numele_metodei(arguments)Am făcut asta de mai multe ori. Pentru
exemplu, apelând lanumără()metodă pe un ș ir:
>>> sSunt un obiect de tip ș ir, o instanț ă a clasei ș ir
>>> [Link]ără('a')

Cel mai adesea, tipurile încorporate ale Python nu sunt suficiente pentru a modela datele pe care le

vrem, aș a că ne-am construit propriile tipuri (sau clase) care modelează datele exact aș a cum
avem nevoie.

O modalitate bună de a gândi la asta este că o clasă este un formator de prăjituri ș i o instanț ă a
această clasă este cookie-ul pe care l-am tăiat.

162
17.2 - Definirea unui nou tip
Să zicem că am vrut să modelămTimpTipurile de date încorporate din Python nu vor
a fi suficient, a modela acest lucru cu uș urinț ă ș i logic. În schimb, am crea noi
propriuTimpclasă. Definim o nouă clasă folosindclasădeclaraț ie.

[Link]:
2. trece

Am definit acum o nouă clasă numită timp. Ca o notă laterală,trecebasically


înseamnă „a nu face nimic”. L-am pus acolo pentru ca programul nostru să nu se blocheze.

Salvează codul de mai sus într-un fiș ier numit my_time.py ș i importă-l astfel:

>>>de laimporta_timpul_meu

>>> t= Time()
>>>tip(t)
<clasa'[Link]'>
>>>esteinstanț ă(t, Time)

Adevărat
>>>print(t)
<time.Timeobjectat0x000001A7C6902F60>

Putem vedea căt este de tipTimpș iteste o instanț ă deTimpș i putem să o vedem
este un obiect stocat la adresa de memorie0x000001A7C6902F60.

Vrem să reprezentăm timpul înore, minute, ș isecundePrin urmare, putem


definiț i o metodă care iniț ializează timpul deTimpobiecte. Vrem de asemenea să
define a afişa()metodă care va afiș a ora:

[Link]:
2.
3. defset_time(time_obj, ore, minute, secunde):
4. time_obj.hours = hours
5. time_obj.minute = minute
6. time_obj.seconds = seconds
7.
8. defdisplay(time_obj):
9. print("Ora este {}:{}:{}".format(time_obj.hours,
10. time_obj.minutes,
11. time_obj.seconds))

În definiț ia clasei de mai sus,set_time()metoda necesită patru argumente.


Primul este obiectul de timp pe care dorim să-l iniț ializăm, iar celelalte trei sunt
ore, minute ș i secunde pe care dorim să le stabilim pentru obiectul nostru de timp.

163
Aș a cum este arătat mai sus, accesăm atributele ore, minute ș i secunde folosind
operatorul de perioadă de exemplutime_obj.hours = hoursAsta
spune, pentru moment
obiectul care a fost trecut, setează atributul său ore la orele trecute ca un
argument.

Înafiș are()metodă, accesăm orele, minutele ș i secundele folosind


operator de punct
Acum să vedem cum putem folosi această clasă:

>>>de latimpul_meuimportTimp

>>> t= Time()
>>> Time.set_time(t,11, 32, 45)
>>> [Link](t)
Ora este 11:32:45
>>> t2= Timp()
>>> Time.set_time(t2,22, 43, 17)
>>> [Link](t2)
Ora este 22:43:17
>>> [Link](t)

Este ora 11:32:45

Putem vedea că avem două obiecte de timp diferite. Creăm un obiect de


theTimpapelând clasa ca ș i cum ar fi o funcț ie. Apelând clasa ca o
funcț ia va crea o instanț ă a clasei ș i va returna o referinț ă la aceasta.

17.3 - Variabila self


După cum s-a văzut în secț iunea precedentă, a trebuit să apelăm la metode făcând referire la
clasă în care aparț ine, de [Link](t)Cu toate acestea, nu a trebuit să facem
că atunci când apelăm metode pe tipurile încorporate în Python, de [Link]ără('a'). Este
se pare că aceasta este doar o prescurtare [Link](s, 'a').

Putem adopta aceeaș i abordare pentru noiTimpclasă:


>>>dinmy_timeimportTime
>>> t= Timp()
>>> t.set_time(11, 32, 45)
>>> [Link]()

164
Este ora 11:32:45

Observaț i cum trebuie să trecem doar trei argumente laset_time()metodă


mai degrabă decât cele patru pe care le-am declarat. Acest lucru se datorează faptului că atunci când invocăm o instanț ă

metodă pe un obiect, acel obiect este trecut automat ca primul argument


metodei. Prin urmare, furnizăm un argument mai puț in decât numărul pe care îl
declarată în definiț ia metodei. Python va furniza automat
obiect lipsă ca primul argument în numele nostru.

By convention, this first parameter, which we’ve been calling obj_timp, este
denumitsinAcesta se referă la instanț a pe care metoda este aplicată.
face metodeleset_time()ș iafiseaza()metode de instanț ă.
Metodele de instanț ă sunt metode care acț ionează asupra unei instanț e particulare a unui obiect.
Primul său parametru este întotdeauna obiectul asupra căruia va opera. În mod implicit,
Toate metodele din clase sunt metode de instanț ă, cu excepț ia cazului în care le declarăm ca fiind metode de clasă.

metodele la care vom ajunge într-un capitol ulterior.

Prin urmare, putem rescrie clasa noastră astfel:

[Link]:
2. defset_time(self, ore, minute, secunde):
3. [Link] = hours
4. [Link] = minutes
5. [Link] = secunde
6.
7. defdisplay(self):
8. "Ora este {}:{}:{}'.format([Link],
9. [Link],
10. [Link]))

Ș i îl putem folosi astfel:


>>>de lamy_timeimportTime

>>> t= Timp()
>>> t.set_time(11, 32, 45)
>>> t2= Timp()
>>> t2.stabileste_timpul(22, 34, 18)
>>> [Link]()
Ora este 11:32:45
>>> [Link]()

Ora este 22:34:18

165
Voi lăsa asta aș a pentru acest capitol. Există multe de asumat aici ș i
este cu adevărat lucruri importante! Restul cărț ii va fi concentrat exclusiv pe obiecte-
programare orientată pe obiect. Aș adar, asiguraț i-vă că înț elegeț i materialul din acest
rezervaț i ș i completaț i exerciț iile următoare.

17.4 - Exerciț ii
Întrebare 1
Scrie o clasă care modelează unLampăClasa lampă va avea două metode.
prima va inicializa lampa ș i este apelatăconectare(). Acest lucru va seta
theis_on atribut care este un boolean pentruFalsA doua metodă este
apelatcomută()Dacă lampa este stinsă, o va aprinde.este_activatcătreAdevărat) ș i dacă
lampa este aprinsă, o va stinge (setis_on pentruAdevărat).

Clasa ta poate fi importată ș i utilizată astfel:


>>>de lamy_lampimportLamp

>>> la= Lampă()


>>> la.plug_in()
>>>print(la.is_on)
Fals
>>> [Link]()
>>>print(la.is_on)
Adevărat
>>> [Link]()
>>>print(la.is_on)

Fals

Întrebarea 2
Scrie o clasă care modelează unCerculClasa cercului va avea patru metode.
mai întâi se va iniț ia cercul. Cinitialise()metoda ar trebui să ia trei
parametriix_coord, y_coord, ș irazaAceasta va seta x ș i y ale cercurilor
coordonate ș i raza sa. Următoarea metodă se numeș tecalc_aria(). Ar trebui să
calculati aria cercului (cautati formula). A treia metoda este
apelatcalc_perimetru()ș i ar trebui să calculeze circumferinț a cercului
(Caută formula). A patra metodă estese suprapune(). Ar trebui să dureze ca un
argument, un alt cerc ș i afiș aț i dacă cele două cercuri se suprapun sau nu.
166
Clasa ta poate fi importată ș i utilizată astfel:
>>>de lamy_circleimportCircle

>>> c1= Cercul()


>>> [Link](2, 2, 4)
>>> c2= Cerc()
>>> [Link](3, 2, 2)
>>> c1.calc_perimetru()
25.13
>>> c2.calc_perimetru()
12.57
>>> c1.calc_area()
50.27
>>> [Link] suprapune(c2)
Adevărat

Sugestie: Definiț ia metodelor de suprapunere ar trebui să fiese suprapune(self,


alt_cerc)

Întrebarea 3
Scrieț i o clasă care să modeleze notele unui student pentru modulele particulare. Clasa
va avea patru metode. Prima ar trebui să iniț ializeze studentul. Studentul
ar trebui să aibă un nume ș i o vârstă. Notele ar trebui modelate ca un dicț ionar
in which the key is the name of the module and the value is the grade. This
ar trebui să fie iniț ial gol. A doua metodă se numeș teadaugă_modul()ș i
ar trebui să adăugaț i un modul la obiectul student. Al treilea este
apelatupdate_module_grade()ș i ar trebui să actualizeze nota pentru un anumit
modulul. Ultima metodă se numeș teafiș ează_note() ș i ar trebui să afiș eze
module studenț i ș i nota asociată fiecărui modul.
Clasa dumneavoastră poate fi importată ș i utilizată după cum urmează:

>>>de laimportăStudentulMeu

>>> s1= Student()


>>> [Link]("Noah",19)
>>> [Link]ă_modul("Python")
>>> s1.update_module_grade("Python",87)

167
>>> [Link]ă_modul("Reț ele")
>>> [Link]ă_notă_modul(77)
>>> s1.arata_note()
Notele lui Noah sunt:

Python:87
Reț ele:77

Indicaț ie: Asigură-te că iniț ializezi corect dicț ionarul de note!

168
Capitolul 18 - OOP: Metode Speciale ș i
Supraîncărcarea operatorilor

18.1 - Metoda __init__()


În capitolul anterior am analizat cum să definim tipuri noi prin crearea
clase. De asemenea, a trebuit să iniț ializăm obiectele noastre de instanț ă folosind metode
îmi placeinitialize()Nu trebuie să facem asta cu tipurile încorporate ale lui Python, cum ar fi
ș iruri.

De exemplu, pentru a iniț ia o listă, am putea să tastăm doarlista_mea = [1, 2, 3].

Putem defini o metodă specială numită__init__()(asta e dublu subliniat).


Acesta se numeș te constructor. Dacă oferim acea metodă pentru clasa noastră, atunci este
apelat automat atunci când creăm un obiect. Prin urmare, putem înlocui orice
metodele de iniț ializare pe care le-am definit anterior cu__init__()Acest lucru permite
ne permite să creăm ș i să iniț ializăm obiectul nostru într-un singur pas.

Să ne uităm la unPunctcare modelează un punct.

[Link]:
2. def__init__(self, x, y):
3. self.x = x
4. self.y = y
5.
6. defdisplay(self):
7. print("Coordonata X: {} Coordonata Y: {}".format(self.x, self.y))

Acum putem folosi clasa noastră de punct astfel:

>>>de la my_point importă Punct


>>>p1=Point(3,4)
>>>[Link]()
X coordinate:3
Y coordinate:4

După cum puteț i vedea, nostru__init__()metoda a fost apelată automat când noi
am creat o instanț ă a clasei punct.

Dacă__init__() metoda ia două argumente (excluzând self), apoi trebuie să


trebuie să treci două argumente, altfel vom primi o eroare.

>>>de la my_point importă Point


>>>p1=Point()
Urmează înapoi (apelul cel mai recent ultim):
Fiș ier "<stdin>", linia 1, în <modul>

169
TypeError:__init__() missing2required positional arguments:'x'and'y'

Cu toate acestea, putem seta valori implicite pentru aceș ti argumenti. Acest lucru ne va permite să
iniț ializează o instanț ă dePunctfără a trece argumentele:

[Link]:
2. def__init__(self, x=0, y=0):
3. self.x = x
4. self.y = y
5.
6. defdisplay(self):
7. print("Coordonata X: {} Coordonata Y: {}".format(self.x, self.y))

Acum putem folosi clasa noastră astfel:

>>>from my_point import Point


>>>p1=Punct()
>>>[Link]()
X coordinate:0
Y coordinate:0

Ce se întâmplă când definim această metodă specială ș i creăm o instanț ă este:

• Python creează o instanț ă goală aPunctclasă.


• Acest obiect gol este trecut, împreună cu3 ș i4pentru
cel__init__() metodă.
• __init__() iniț iază obiectul cu argumentele furnizate
• Se creează o referinț ă la obiectul iniț ializat ș i se atribuie luip1.

Aminteș te-ț i, metodele speciale nu sunt apelate niciodată direct!

18.2 - Metoda __str__()


The__str__() metoda este o altă funcț ie specială. Putem să o suprascriem care
înseamnă că putem schimba implementarea sa ș i, prin urmare, comportamentul său.

Când sunămprint()pe un incorporat Python, cum ar fi un ș ir sau o listă, obț inem un


reprezentare bine formatată, uș or de citit a obiectului.

Sub capotă,listătipul încorporat implementează acest lucru__str__() metodă ș i


deci, ne permite să tipărim listele noastre într-un format uș or de citit pentru oameni.

Putem suprascrie această metodă pentru a ne permite să formatăm ș i să imprimăm obiectele noastre aș a cum dorim.

a considera potrivit. Prin urmare, când apelămprint()pe un obiect al unei clase pe care am definit-o,

nu ne vom mai obț ine ceva de genul<[Link] object at


0x000001A7C6902F60tipărit la terminal.

170
Facem acest lucru returnând un ș ir formatat. Să vedem cum am putea face asta.
pentruPunctclasă. Acum am putea înlocuiafiseaza()funcț ie ș i înlocuieș te-o
cu__str__(), astfel putem să tipărim doar instanț a noastră de punct.

[Link]:
2. def__init__(self, x=0, y=0):
3. self.x = x
4. self.y = y
5.
6. def__str__(self):
7. reîntoarce"Coordonata X: {} Coordonata Y: {}".format(self.x, self.y)

Acum putem folosi clasa noastră după cum urmează:

>>>de la my_point import Point


>>>p1=Punct(2,3)
>>>print(p1)
X coordinate:2
Y coordinate:3

Valoarea de returnare a acestei metode speciale trebuie să fie un obiect de tip ș ir.

18.3 - Metoda __len__()


Aș a cum probabil îț i poț i imagina, __len__()metoda ne permite să suprascriemo
implementarea implicită alen()funcț ia de a defini lungimea noastră
tipurile proprii sunt. De exemplu, cu unPunct, lungimea poate fi distanț a de la
originele (punctul (0, 0)). Cu toate acestea, trebuie să returnăm un număr întreg. Vom obț ine
o eroare altfel. Aș adar, va trebui să rotunjim fie în sus, fie în jos. Python face acest lucru
pentru a facelen()funcț ie previzibilă. În acest exemplu, vom arunca doar
valoarea de returnare a noastră ca un integer:

[Link]:
2. def __init__(self, x=0, y=0):
3. self.x = x
4. self.y = y
5.
6. def__str__(self):
7. Returnează "Coordonata X: {} Coordonata Y: {}".format(self.x, self.y)
8.
9. def__len__(self):
10. distance_from_center = ((self.x)**2 + (self.y)**2)**0.5
11. returndistance_from_center

Putem acum să numimlen()funcț ia pe instanț ele noastrePunctclasă.

>>>de la my_point importă Point


>>>p1=Point(24,33)
>>>len(p1)
40

Distanț a actuală a acestui punct faț ă de centru este de 40.8044...

171
Este regretabil că nu putem returna un număr în virgulă mobilă, prin urmare, dacă noi
dacă vrem o acurateț e reală, va trebui să implementăm o metodă diferită pe care o vom avea
a apela la instanț ă.

18.4 - Suprascrierea operatorilor

Există o grămadă de metode speciale în Python, nu o să le acopăr.


toate, cu toate acestea, există câteva metode speciale care sunt apelate atunci când folosim
operatori. De exemplu, atunci când folosim operatorul de comparaț ie==pe doi
numere întregi, o metodă specială numită__eq__()se numeș te.

Când suprascrierea metodei este efectuată pe metode care definesc comportamentul


în ceea ce priveș te operatorii, numim asta: suprascrierea operatorilor.

Putem suprasolicita comportamentul implicit al== metodă, astfel încât să se aplice la


nostruPunctclasă. Acest lucru se face astfel:

[Link]:
2. def __init__(self, x=0, y=0):
3. self.x = x
4. self.y = y
5.
6. def__str__(self):
7. Coordonata X: {} Coordonata Y: {}
8.
9. def__len__(self):
10. distance_from_center = ((self.x)**2 + (self.y)**2)**0.5
11. returnare(int(distanta_de_la_centru))
12.
13. def__eq__(self, other):
14. return((self.x, self.y) == (other.x, other.y))

În acest caz, suprasolicităm__eq__()metodă prin compararea a două tuple. Dacă


două tupluri, fiecare conț inând coordonatele x ș i y ale punctelor, sunt egale, atunci
cele două puncte sunt egale. Putem folosi acest lucru astfel:

>>>de la mytime importă Point


>>>p1=Point(2,2)
>>>p2=Punct(2,2)
>>>p1==p2
Adevărat
>>>p3=Punct(2,3)
>>>p1==p3
Fals

Am putea adăuga, de asemenea, două puncte pentru a obț ine un nou punct. În acest caz, noi
ar suprasolicita__add()__ metodă. The__add__() metoda implementează
funcț ionalitatea + operator, nu+=operator. Prin urmare, trebuie să ne întoarcem
un nou obiect ca+ operatorul nu este pentru adunare în loc.

172
Să ne uităm la asta:

[Link]:
2. def__init__(self, x=0, y=0):
3. self.x = x
4. self.y = y
5.
6. def__str__(self):
7. return "Coordonata X: {} Coordonata Y: {}".format(self.x, self.y)
8.
9. def__len__(self):
10. distance_from_center = ((self.x)**2 + (self.y)**2)**0.5
11. returnează int (distanț a de la centru)
12.
13. def__eq__(self, altul):
14. return((self.x, self.y) == (other.x, other.y))
15.
16. def__adăuga__(self, other):
17. new_x = self.x + other.x
18. new_y = self.y + other.y
19. returnPoint(new_x, new_y)

Acum putem folosi această metodă după cum urmează:

>>>de la my_point import Point


>>>p1=Point(2,3)
>>>p2=Punct(5,2)
>>>p3=p1+p2
>>>print(p3)
X coordinate:7
Y coordinate:5

Putem supraîncărca+=operator, care este pentru adăugare în loc. În acest fel, noi
nu trebuie să returnezi o referinț ă la un nou obiect punct ș i să o asignezi unei
variabilă nouăp3în schimb, actualizăm obiectul(ă)p1în acest caz) atributele de date.

173
Acest lucru se face prin suprasarcina__iadd()__ metodă.

[Link]:
2. def__init__(self, x=0, y=0):
3. self.x = x
4. self.y = y
5.
6. def__str__(self):
7. return"Coordonata X: {} Coordonata Y: {}".format(self.x, self.y)
8.
9. def__len__(self):
10. distance_from_center = ((self.x)**2 + (self.y)**2)**0.5
11. returnint(distanta_de_la_centru)
12.
13. def __eq__(self, other):
14. return((self.x, self.y) == (other.x, other.y))
15.
16. def__adăuga__(self, other):
17. new_x = self.x + other.x
18. new_y = self.y + other.y
19. returneazăPunct(nou_x, nou_y)
20.
21. def__iadd__(self, altul):
22. temp_point = self + other
23. self.x, self.y = temp_point.x, temp_point.y
24. returnează-te

Acum putem folosi+=operator pe punctele noastre

>>>de la my_point import Point


>>>p1=Coordonată(2,2)
>>>p2= punct(5,2)
>>>p1+=p2
>>>print(p1)
X coordinate:7
Y coordinate:4

Fii atent când supraîncarci operatorii in-place. În acest caz, folosim să creăm un
punct temporar ș i apoi actualizaț isineinstanț ă folosind atribuirea multiplă.
Îț i aminteș ti când am schimbat valoarea dintr-o variabilă cu alta ș i noi
a trebuit să creăm o variabilă temporară? Putem face asta mult mai repede făcândx, y = y,
x. În acest cazx, yș iy, xsunt tupluri!

Oricum, după ce actualizăm atributele pentruautotrebuie să ne întoarcemsin.

Mai jos este o listă de alț i operatori pe care îi poț i suprascrie.

MetodaOperator care poate fi suprascrisă


== __eq__()
!= __ne__()
< __lt__()
<= __le__()
> __gt__()
174
Metoda Operator care poate fi suprascrisă
>= __ge__()
+ __add__()
- __sub__()
// __floordiv__()
/ __truediv__()
* __mul__()
** __pow__()
% __mod__()
+= __iadd__()
-= __isub__()
*= __imul__()
//= __ifloordiv__()
/= __itruediv__()
**= __ipow__()
Există mai multe, dar nu vom avea nevoie de altele, de fapt nu vom folosi.
jumătate din acestea în această carte.

18.5 - Exerciț ii
Întrebarea 1
Creează unContBancarclasa. Clasa contului bancar ar trebui să aibă următoarele
attributes: echilibrusiaccount_ownerClasa contului bancar ar trebui să
a aveadepozitș iretragemetode. De asemenea, ar trebui să fiț i capabil săimprimarebanca
cont, pentru a afiș a numele proprietarului contului ș i soldul. Când
implementează corect, ar trebui să poț i folosi clasa cont bancar ca
urmează:

>>>account=BankAccount("John Smith")
>>>print(contul)
Owner: John Smith
Balance: $0
>>>[Link](200)
>>>print(contul)
Owner: John Smith
Balance: $200
>>>[Link](50)
>>>print(account)
Owner: John Smith
Balance: $150
>>>[Link](200)# Not enough in the account to withdraw 200
>>>print(acest cont)
Owner: John Smith

175
Balance: $150

Întrebarea 2
Create a Linieclasă. Clasa linie ar trebui să aibă patru atribute: unx1ș i
oy1coordonate pentru un punct pe linie ș i unx2ș i uny2coordonate pentru
al doilea punct pe linie. Ar trebui să poț i face câteva lucruri cu un
instanț a unei linii. Ar trebui să poț i apela lalenmetodă pe o linie pentru a arăta
lungimea sa, adaugă două linii împreună, scade două linii, înmulț eș te o linie cu un
integertipăriț i linie ș i compară două linii pentru a vedea dacă sunt egale. În acest
egalitatea cazurilor înseamnă că ambele linii au aceeaș i lungime. Când este implementată
Corect, ar trebui să poț i utiliza clasa Line după cum urmează:

>>>lineOne=Line(2,2,4,4)
>>>lineTwo=Line(1,1,3,3)
>>>len(liniazăUnu)
2
>>>linieTrei=linieUnu+linieDouă
>>>len(liniaTrei)
4
>>>lineFour=lineOne-lineTwo
>>>len(liniaPatru)
1
lineFive=lineTwo*3
>>>len(liveFive)
6
>>>print(lineOne)
Line Details:
Point1: (2,2)
Point2: (4,4)
>>>print(liniaUnu==liniaDoi)
Adevărat
>>>print(lineOne==lineFive)
Fals

Notă: Lungimea liniei trebuie să returneze un număr întreg.

176
Capitolul 19 - OOP: Tipuri de Metode &
Modificatori de acces

19.1 - Ce sunt metodele de instanț ă?


Până la sfârș itul acestui capitol ar trebui să fii pregătit pentru primul tău proiect!

Deja ne-am întâlnit cu metodele de instanț ă. Ele sunt tipul de metode pe care le avem
am lucrat în ceea ce priveș te programarea orientată pe obiect până în acest moment.

Metodele de instanț ă sunt cel mai comun tip de metode în clase. Ele sunt
se numesc metode de instanț ă deoarece acț ionează asupra instanț elor specifice ale unei clase. Ele pot

accesaț i atributele de date care sunt unice pentru acea clasă.

De exemplu, dacă avem oPersoanăclasă, atunci fiecare instanț ă a unei persoane poate
au un nume unic, vârstă etc. Metodele de instanț ă aueuca primul
parametru, ș i acest lucru ne permite să trecem prinautopentru a accesa atributele datelor
unic pentru acea instanț ă ș i, de asemenea, alte metode care pot reside în cadrul nostru
clasă.

Nu o să ofer un exemplu pentru metodele de instanț ă aș a cum le-am văzut.


de atâtea ori!

19.2 - Ce sunt metodele de clasă?


Metodele de clasă sunt al doilea tip de metodă OOP pe care îl putem avea. O clasă
metoda cunoaș te despre clasa sa. Ele nu pot accesa datele care sunt specifice unei
instanț ă, dar pot apela alte metode.
Metodele de clasă au acces limitat la metodele din interiorul clasei ș i pot modifica
detalii specifice ale clasei, cum ar fi variabilele clasei, pe care le vom vedea în momentul următor. Acest

ne permite să modificăm starea clasei care va fi aplicată în toate instanț ele


din clasă. Ele sunt unul dintre cele mai confuze tipuri de metode. Metodele de clasă
sunt de asemenea legate în permanenț ă de clasa sa.

Invocăm metodele de clasă printr-o instanț ă sau printr-o clasă. Spre deosebire de
metode de instanț ă al căror prim parametru estesinonim, cu metode de clasă, este primul
parameter is not an object, but the class itself. This first parameter is called cls.
Folosim un decorator pentru a marca o metodă ca fiind o metodă a clasei. Decoratorul
este@classmethod.

177
Să ne uităm la un exemplu întorcându-ne la nostruTimpclasă. Vrem o funcț ie
care poate converti secunde în format de 24 de ore cu ore, minute ș i secunde.
Această metodă ar trebui să fie legată de clasa deTimpmai degrabă decât un specific
instanț ă.

[Link]:
2. def __init__(self, ore=0, minute=0, secunde=0):
3. [Link] = hours
4. [Link] = minutes
5. [Link] = seconds
6.
7. def__str__(self):
8. Timpul este {:02}:{:02}:{:02}
9. [Link],
10. [Link])
11.
12.# ALTE METODE POT FI AICI...
13.
14. @classmethod
15. defseconds_to_time(cls, s):
16. minute, secunde = divmod(s, 60)
17. ore, minute = divmod(minute, 60)
18. extra, ore = divmod(ore, 24)
19. returneazăcls(ore, minute, secunde)

Pentru acest exemplu, am exclus celelalte metode de instanț ă de care nu ne pasă.


deocamdată. Metoda de clasă seconds to time ia clasa ca primă
parametru ș i un număr de secunde,s, ca al doilea său parametru.

O notă suplimentară despre funcț ia divmod(): Thedivmod()funcț ia ia două


argumente, primul este numărul de secunde pe care vrem să le convertim în 24 de ore
timp, secunda va fi divizată în acesta (60 în acest caz). Acest lucru returnează un tuplu în
care primul element este numărul de ori în care al doilea parametru a fost împărț it
în primul, iar al doilea element al tuplului este restul după aceea
diviziune. De exemplu, dacă am numitdivmod(180, 60), am primi un tuplu de (3,
0) în care folosim atribuirea multiplă pentru a asigna 3 minutelor ș i 0 la
secundele, care este ceea ce ne aș teptăm, fiind 180 de secunde, sunt 3 minute.

Înapoi la metoda noastră de clasă. Când am calculat orele, minutele ș i


secunde, ne întoarcemcls(oore, minute, secunde). clsva fi înlocuit
cuTimpîn acest caz. Aș a că, într-adevăr, revenim la un nouTimpobiect.

Pentru a vedea acest lucru în acț iune:

>>>de lamy_timeimportTime

178
>>> t= Time.seconds_to_time(11982)
>>>print(t)

Este ora 03:19:42

Am menț ionat ș i variabilele de clasă mai devreme. La fel ca înainte, variabilele de clasă sunt
legat de o clasă mai degrabă decât de o instanț ă specifică. Putem folosi o metodă a clasei pentru a

verifică de câte ori a fost creată o instanț ă a clasei timp pentru


exemplu.
Conform convenț iei, variabilele de clasă sunt de obicei scrise complet cu majuscule pentru variabilă
nume. Să modificăm clasa noastră de timp de mai sus pentru a adăuga o metodă de clasă

numitNUMĂRcare va număra de câte ori o instanț ă a clasei a fost


a fost creat.

[Link]:
2.
3. COUNT = 0
4.
5. def __init__(self, ore=0, minute=0, secunde=0):
6. [Link] = hours
7. [Link] = minutes
8. [Link] = seconds
9. [Link] += 1
10.
11. def__str__(self):
12. Timpul este {:02}:{:02}:{:02}
13. [Link],
14. [Link])
15.
16.# ALTE METODE POT FI AICI...
17.
18. @classmethod
19. defsecunde_la_timp(cls, s):
20. minute, secunde = divmod(s, 60)
21. ore, minute = divmod(minute, 60)
22. extra, ore = divmod(ore, 24)
23. returnează cls(ore, minute, secunde)

Observaț i cum avem un nouNUMĂRvariabilă chiar înainte de constructorul nostru ș i în interior


constructorul nostru, după ce a iniț ializat toate atributele, creș temNUMĂRclasă
variable by 1. Now we can see how many times instance of our class has been
creat.
>>>de lamy_timeimportTime

>>> t1 = Timp23, 11, 37)


>>> t2= Timp()
>>> [Link]
2

179
>>> t3= Timp12, 34, 54)
>>> [Link]

Poate fi complicat să îț i dai seama când să foloseș ti aceste lucruri. Ca o regulă generală,
o metodă poate fi invocată (ș i are sens să) în absenț a unei instanț e,
atunci se pare că, această metodă este un bun candidat pentru o metodă de clasă.

19.3 - Ce sunt metodele statice?


În final, avem un al treilea tip de metodă care se numeș te metodă statică. Acestea sunt
nu la fel de confuze ca metodele de clasă. Poț i să te gândeș ti la metodele statice exact ca
funcț ii obiș nuite. Python nu va furniza automat argumente suplimentare
când este invocată o metodă statică. Spre deosebire desinelș icls cu instanț ă ș i clasă
methods.

Metodele statice sunt metode care sunt legate de clasă într-un fel, dar
nu este nevoie să accesaț i date specifice clasei ș i nu este nevoie de o instanț ă pentru a fi
invocate. Le poț i apela pur ș i simplu când doreș ti.

În general, metodele statice nu ș tiu nimic despre starea clasei. Ele sunt
metode care acț ionează mai degrabă ca utilităț i.

Folosim@staticmethoddecorator pentru a specifica o metodă statică. Vom adăuga o


metodă statică pentru al nostruTimpclasă care va valida timpul pentru noi, verificând că

orele sunt în intervalul 0 ș i 23, iar minuturile ș i secundele noastre sunt


în intervalul 0 ș i 59.

[Link]:
2.
3. COUNT = 0
4.
5. def __init__(self, ore=0, minute=0, secunde=0):
6. [Link] = hours
7. [Link] = minutes
8. [Link] = seconds
9. [Link] += 1
10.
11. def__str__(self):
12. Timpul este {:02}:{:02}:{:02}.format([Link],
13. [Link]
14. [Link])
15.
16.# ALTE METODE POT FI AICI...
17.
18. @classmethod
19. defseconds_la_timp(cls, s):
20. minute, secunde = divmod(s, 60)
21. ore, minute = divmod(minute, 60)

180
22. extra, ore = divmod(ore, 24)
23. returneazăcls(ore, minute, secunde)
24.
25.
26. @staticmethod
27. def valida(hours, minutes, seconds):
28. 0 <= ore <= 23 ș i 0 <= minute <= 59 ș i 0 <= secunde <= 59

Această metodă statică este pur ș i simplu o utilitate care ne permite să verificăm că orele sunt
corect. Am putea folosi asta pentru a opri un utilizator să creeze un timp atât
ca35:88:14deoarece nu ar avea niciun sens logic.
de lamy_timeimportTime
>>> [Link](5, 23, 44)
Adevărat
>>> [Link](25, 34, 63)
Fals
>>> t= Timp22, 45, 23)
>>> [Link]([Link], [Link], [Link])
Adevărat

Poate fi, de asemenea, dificil să observi când să foloseș ti metodele statice, dar din nou, dacă găseș ti

că ai o funcț ie care ar putea fi utilă, dar nu va fi aplicabilă oricărei


o altă clasă, dar în acelaș i timp nu trebuie să fie legată de o instanț ă ș i
nu este nevoie să acceseze sau să modifice datele vreunei clase, atunci este un candidat bun
pentru o metodă statică.

19.4 - Atribute publice, private ș i protejate


În programarea orientată pe obiect, ideea de modificatori de acces este importantă. Este
ne ajută să implementăm ideea de Încapsulare (ascunderea informaț iilor). Acces
modificatorii spun compilatoarelor ce alte clase ar trebui să aibă acces la date
atributele ș i metodele care sunt definite în cadrul claselor. Acest lucru opreș te exteriorul
clase din apelarea metodelor sau accesarea datelor dintr-o altă clasă, sau
făcând acele atribute ș i metode de date publice, caz în care toate celelalte
clasele le pot apela ș i accesa.
Modificatorii de acces sunt utilizaț i pentru a face codul mai robust ș i mai sigur prin limitarea

acces la variabile care nu trebuie să fie accesate de fiecare (sau poate că da)
în care sunt publice).

181
Până acum am folosit atribute ș i metode publice. Clasele pot apela
metodele ș i accesul la variabilele din alte clase.
În Python, nu există o verificare strictă pentru modificatorii de acces, de fapt ei nu
există, dar programatorii Python au adoptat o convenț ie pentru a o depăș i.

Următoarele atribute sunt publice:

1.def__init__(self, ore, minute, secunde):


2. [Link] = hours
3. [Link] = minutes
4. [Link] = seconds

Prin convenț ie, acestea sunt accesibile oricărei persoane (prin oricine mă refer la alț ii)

cursuri).
Pentru a "face" aceste variabile private, adăugăm o linie dublă de subliniere în faț a
numele variabilei. Ca un atribut sau metodă să fie privată, înseamnă că doar
clasa în care sunt conț inute poate să le apeleze ș i să le acceseze. Nimic din exterior.
În limbajul Java, dacă ai două clase ș i ai încercat să apelezi o metodă privată
dintr-o altă clasă ai primi o eroare.

1.def__init__(self, ore, minute, secunde):


2. self.__hours = hours
3. self.__minute = minute
4. self.__seconds = seconds

Al treilea modifier de acces despre care voi vorbi este protejat. Acesta este la fel ca privat
cu toate că toate subclasele pot, de asemenea, să acceseze metodele ș i variabilele de membru. Voi
vorbeș te despre subclase în următorul capitol, aș a că nu-ț i face griji în legătură cu asta acum, dar

prin convenț ie, folosim un singur underscore înainte de numele variabilei.

1.def__init__(self, ore, minute, secunde):


2. self._hours = hours
3. self._minutes = minutes
4. self._seconds = seconds

19.5 - Exerciț ii
Întrebarea 1
Scrie un program Python care conț ine o clasă denumităPersoanăO instanț ă de
oPersoanăar trebui să aibă atribute de nume ș i vârstă. Ar trebui să poț i să tipăreș ti un
instanț a clasei care, de exemplu, ar trebui să afiș ezeJohn are 28 de ani.

182
Clasa ta ar trebui să aibă o metodă numitădinAnulDeNaș tere() care are ca parametrii
ar trebui să ia o vârstă ș i un an de naș tere. De exemplu,deLaAnulNaș terii('John',
1990)ar trebui să returneze o instanț ă dePersoanăcare are 29 de ani (la momentul
scriind această carte, 2019).

Rularea programului tău ar trebui să producă următoarele:

>>>de lamy_personimportPerson

>>> ioan= Person("John",28)


>>>print(ioan)
John are 28 de ani
>>> adam= Persoană.dinAnulNaș terii("Adam",1990)
>>>print(adam)
Adam are 29 de ani

Gândeș te-te cu atenț ie la ce tip de metodă să foloseș ti.

Întrebarea 2
Scrie unStudentclasă care iniț iază un student cu 3
attributes: nume, noteș istudent_numberNota ar trebui să fie un dicț ionar de
module la note. Numărul de student al primei instanț e a studentului ar trebui să fie
Numărul studentului al doilea student ar trebui să fie 19343553.
19343554 ș i aș a mai departe. Ar trebui să ai trei metode,adauga_modul()care
primeș te un parametru, un nume de modul, ș i iniț iază nota la 0.
a doua metodă ar trebui să fie,actualizează_modul()care ia două parametrii,
numele modulului ș i nota pentru modul. Metoda finală ar trebui să permită
utilizatorul să imprime un student.

Gândiț i-vă cu atenț ie la cum veț i implementa creș terea numărului de studenț i.
Executarea programului tău ar trebui să dea următoarea ieș ire:

>>>de lamy_studentimportStudent

>>> iohane= Student("John")


>>> [Link]ă_modul("Python")
>>> [Link]ă_modul("Python",88)
>>>print(ioan)
Name: John
Număr de student:19343553

183
Grades:
Python88
>>> adam= Student("Adam")
>>> adam.adauga_modul("Java")
>>> [Link]ă_modul("Java",60)
>>>print(adam)
Name: Adam
Numărul studentului:19343554

Grades:
Java:60

Întrebarea 3
ModificăStudentclasă pentru a include o metodă care va valida notele. O notă
ar trebui să fie între 0 ș i 100.

Gândeș te-te cu atenț ie la tipul de metodă care ar trebui să fie aceasta.

>>>de la studentul_meu importă Student


>>> john = Student("John")
>>> [Link]ă_modul("Python")
>>> [Link](88)
Adevărat
>>> [Link](101)
Fals
>>> [Link]ă_modulul("Python",88)
>>>print(ion)
Name: John
Număr student:19343553
Grades:

Python88

Proiect
Eș ti însărcinat cu crearea unei aplicaț ii de simulare a reț elei în care două
partidele există. Vom numi aceste partideExpeditorș iRecepț ionerAr trebui, de asemenea, să
există un proces care verifică continuu dacăExpeditorare vreo pachete de date

184
a trimite, dacă o face, atunci procesul ar trebui să le livereze laDestinatar.
TheExpeditorar trebui să creeze periodic pachete de date care să fie trimise (Acestea pot fi
ș iruri generate aleatoriu). TheReceiverar trebui să verifice periodic dacă are
a primit pachete de date, dacă da, atunci ar trebui să le imprime, apoi să le ș tergă
ei.
Indicaț ie: Ar trebui să reflectezi cu atenț ie asupra ce clase sunt necesare ș i ce
metodele pe care ar trebui să le conț ină. Ceva numit 'buffer' ar putea fi de ajutor aici
pentru procesul tău care mută pachete întreExpeditorș iReceiverCiteș te
despre buffere ș i ce sunt acestea. Gândeș te-te cu atenț ie la ce tipuri încorporate în Python
ar putea fi capabil să implementeze un buffer.

185
Capitolul 20 - Moș tenirea OOP
20.1 - Ce este moș tenirea?
În programare, ne întâlnim adesea cu obiecte care sunt destul de asemănătoare sau este posibil să

vezi că o clasă este un tip de altă clasă. De exemplu, o maș ină este un tip de
vehicul. În mod similar, o motocicletă este un tip de vehicul. Putem vedea o relaț ie
apare aici. Tipul de relaț ie este o relaț ie „este un”.
În programarea orientată pe obiect, numim aceasta moș tenire, iar moș tenirea ajută
modelul us este o relaț ie. Moș tenirea este unul dintre pilonii obiect-
programare orientată pe obiect ș i vom explora aceasta în acest capitol.

Există o terminologie importantă în jurul moș tenirii pe care trebuie să o clarificăm.


before we look any deeper into it. Let’s go back to our example of cars and
motoarele fiind tipuri de vehicule. Dacă privim fiecare dintre acestea ca pe o clasă, noi
aș numi clasa vehicul o clasă de bază sau clasă părinte, iar maș ina ș i
clase de motociclete, clase derivate, clase copil sau subclase (ele pot fi
se referă diferit în funcț ie de ceea ce citeș ti, doar să ș tii că acestea sunt
exact acelaș i lucru).
Putem privi moș tenirea în programare în acelaș i mod în care o facem în viaț a reală
unde un copil moș teneș te trăsături de la părinț ii săi, pe lângă propriile sale
caracteristici unice. În programare, o clasă copil poate moș teni atribute ș i
metode din clasa sa părinte.

20.2 - Clase părinte ș i copil


Putem crea un părinte care va acț iona ca o bază din care subclass-urile pot fi
derivate. Acest lucru ne permite să creăm clase copil prin ereditate fără
fiind nevoit să rescriu acelaș i cod din nou ș i din nou.

Să spunem că avemDreptunghiș iPătratcursuri. Multe dintre metodele ș i


atribute între unDreptunghiș iPătratva fi similar. De exemplu, ambele o
un dreptunghi ș i un pătrat au unsuprafaț ă() ș i unperimetrul(). Până acum noi
ar fi putut implementa aceste clase astfel:

186
[Link]:
2. def__init__(self, lungime, lăț ime):
3. [Link] = lungime
4. [Link] = width
5.
6. defarea(self):
7. [Link] * [Link]
8.
9. defperimetru(self):
10. return2 * [Link] + 2 * auto.lăț ime
11.
[Link]ăPătrată:
13. def__init__(self, lungime):
14. [Link] = length
15.
16. defarea(self):
17. [Link] * [Link]
18.
19. defperimetrul(self):
20. return4 * [Link]

Ș i le-am fi folosit în felul următor:


>>> dreptunghi= Dreptunghi2, 4)
>>> pătrat= Pătrat(2)
>>> pă[Link]ă()
4
>>> [Link]()

Acest lucru pare să fie puț in redundant, totuș i, deoarece atât un pătrat, cât ș i un dreptunghi au
4 laturi fiecare ș i ambele au o suprafaț ă ș i un perimetru. Dacă ne uităm mai multe
privind cu atenț ie această situaț ie, observăm că un pătrat este un caz special al unui dreptunghi
în care toate laturile au aceeaș i lungime.

Putem folosi moș tenirea pentru a reflecta această relaț ie ș i a reduce cantitatea de
cod pe care trebuie să-l scriem. În acest caz unSquare este un tip deDreptunghiastfel încât face
are sens ca un pătrat să moș tenească de la clasa dreptunghi.

Să ne uităm din nou la acest cod, dar de data aceasta am făcut modificări la pătrat.
o clasă pentru a reflecta această relaț ie. Există câteva lucruri noi care se întâmplă aici, dar
Îț i voi explica mai târziu.

[Link]ăDreptunghi:
2. def__init__(self, lungime, lăț ime):
3. [Link] = length
4. [Link] = width
5.
6. defarea(self):
7. [Link] * [Link]
8.
9. defperimetru(self):

187
10. întoarce2 * [Link] + 2 * [Link]
11.
[Link](Rectangle):
13. def__init__(self, lungime):
14. super().__init__(lungime, lungime)

Prima schimbare aici este atunci când definim numelePătratclasă. Eu


a aveaclasă Pătrat(Rectanghe)Aceasta înseamnă căPătratmoș teneș te de la
theDreptunghiclasă.
Următoarea modificare este pentru pătrat__init__() metodă. Putem vedea că suntem
apelând un nousuper()metodă. Thesuper()metoda în Python returnează un proxy
un obiect care deleghează apelurile de metodă către un părinte sau un frate de tip. Asta
definiț ia poate părea puț in confuză, dar ceea ce înseamnă în acest caz este că
am folositsuper()a suna la__init__()metoda deDreptunghiclasă
care ne permite să-l folosim fără a fi nevoie să-l reimplementăm înPătratclasă.
Acum, lungimea unui pătrat estelungimeiar lăț imea sa este de asemenealungimepe măsură ce am trecut

lungimea în dublu faț ă de apelul lasuper()s__init__() metodă.

Deoarece am moș tenitDreptunghiînPătratclasă, avem de asemenea acces la


thesuprafaț ă()ș iperimetrulmetode fără a fi nevoie să le redefinim. Putem
acum foloseș te aceste clase astfel:
>>> dreptunghi= Dreptunghi2, 3)
>>> pătrat= Pătrat(2)
>>>print([Link]())
6
>>>imprimare([Link]())

4
>>>print([Link]())
10
>>>print([Link]())
8

După cum puteț i vedea,super()metoda îț i permite să apelezi metodele de


superclasă în subclasa ta. Principala utilizare a acestui lucru este de a extinde funcț ionalitatea
al metodei moș tenite.
Prin moș tenire putem, de asemenea, să suprascriem metode în clasele noastre copil. Să adăugăm un
o nouă clasă numită aCubCubo va moș teni de la Pătrat (care moș teneș te de la)
Dreptunghi).Cubclasa va extinde funcț ionalitatea metodei area pentru

188
calculează suprafaț a unui cub. De asemenea, va avea o nouă metodă
apelatvolumpentru a calcula volumul cubului. Putem face o utilizare bună
desuper()aici pentru a ne ajuta să reducem cantitatea de cod de care avem nevoie.

Să vedem cum facem asta:

[Link]ăPătrat(Rectangh):
2. def__init__(self, lungime):
3. super().__init__(lungime, lungime)
4.
[Link](Pătrat):
6. defarea(self):
7. side_area = super().area()
8. return6 * aria_laterala
9.
10. defvolum(self):
11. side_area = super().area()
12. returnside_area * [Link]

Acum putem folosi această clasă aș a cum este arătat:

>>> cub= Cub(2)


>>>print([Link]ț a())
24
>>>print([Link]())

După cum puteț i vedea, nu a fost necesar să anulăm__init__() metodă aș a cum este
moș tenit de laPătratÎnsă, am anulatsuprafaț ă()metodă din
clasa părinte (Cadran) peCubpentru a reflecta cum este aria unui cub
calculat. Am folosit de asemeneasuper()metodă pentru a ne ajuta cu acest lucru.

Am extins, de asemenea, funcț ionalitatea cubului pentru a include ovolum()metodă.


Din nou, am folositsuper()metodă de a ajuta cu asta.

După cum puteț i vedea, folosind moș tenirea am redus semnificativ cantitatea de
cod comparat cu modul în care am fi implementat aceste trei clase
anterior.

189
Vreau doar să mă întorc la suprascrierea__init__() metodă pentru un secund. Să
presupune unPersoanăclasă ș i unAngajatclasă care derivă dinPersoană.
Everything about an employee is the same as a Persoanădar angajatul va
de asemenea, au un ID de angajat.

Să vedem cum am implementa aceste lucruri:

[Link]:
2. def__init__(self, nume, vârstă):
3. [Link] = name
4. [Link] = age
5.
6. defshow_nume(self):
7. print("Nume: " + [Link])
8.
9. defshow_age(self):
10. vârsta:
11.
[Link]ăAngajat(Persoană):
13. def__init__(self, nume, varsta, idAngajat):
14. super().__init__(nume, vârstă)
15. [Link] = employeeId
16.
17. defshow_id(self):
18. ID angajat:

Putem acum să le folosim astfel:


>>> persoană= Person("John",32)
>>> emp= Employee("Simon",25, 4532245)
>>> persoană.arată_nume()
Name: John
>>> persoană.arată_vârsta()
Vârstă:32

>>> emp.afiseaza_nume()
Name: Simon
>>> emp.arata_varsta()
Age: 25
>>> emp.show_id()
Employee ID: 4532245

Motivul pentru care îț i arăt asta este că, deș i am arătat deja cum
pentru a suprascrie metode, oamenii se confundă atunci când suprascriu
the__init__()metodă pentru a include de asemenea atribute noi în clasa derivată.

190
20.3 - Moș tenire multiplă
Până acum, am analizat moș tenirea simplă. Adică, clasele copil care moș tenesc de la
o clasă de părinț i unică. Moș tenirea multiplă este atunci când o clasă poate moș teni de la
mai mult decât o clasă părinte.

Th;is allows programs to reduce redundancy, but it can also introduce a certain
nivel de complexitate, precum ș i ambiguitate. Dacă plănuieș ti să faci mai multe
moș tenirea în programele tale, ar trebui să fie făcută cu grijă. Gândeș te-te la
programul tău general ș i cum ar putea afecta acest lucru. De asemenea, ar putea afecta
claritatea programelor tale.

De exemplu:

[Link]:
2. defmetodă():
3. # codul tău aici
4.
[Link]:
6. defmethod():
7. # codul tău aici
8.
[Link](A, B):
10. trece
11.
12.>>> [Link]()

CaremetodăesteC clasa se referă la? Metoda din A sau metoda


din B? Acest lucru ar putea face codul tău mai greu de citit. În Python, când
apelaremetodă()în C, Python verifică mai întâi dacă C are o implementare
dinmetodăapoi verifică dacă A a implementatmetodăÎn acest caz, aș a că foloseș te
dacă nu ar fi făcut-o, atunci Python ar verifica fiecare clasă părinte pe rând (A, B, ...)
ș i aș a mai departe până când găseș te prima clasă părinte care a implementat metoda.

Nu voi intra prea adânc în moș tenirea multiplă, deoarece este destul de auto-
explicativ despre cum să îl foloseș ti, aș a că o să dau doar un exemplu de cum se face
poate fi folosit:

[Link]ăCPU:
2. def__init__(self, num_registers):
3. self.num_registers = registers
4. Alte metode
5.
[Link]ăRAM:
7. def__init__(self, sumă):
8. [Link] = amount
9. Alte metode

191
10.
[Link]ăCalculator:
12. def__init__(self, num_registers, amount):
13. CPU.__init__(număr_registre)
14. RAM.__init__(cantitate)
15.
16. # Alte metode

Acest lucru poate fi folosit astfel:

>>> comp= Computer16, 32)


>>>print(comp.num_registers)
16
>>>print([Link])
32

20.4 - Exerciț ii
Întrebare 1
Create two classes: Persoanăș iAngajat. Clasa persoană ar trebui să
a aveanumeș ivârstăatribute. Clasa angajatului ar trebui să aibă unul
adicionalemployeeId atribut. Angajatul ar trebui, de asemenea, să
a aveaclock_in ș iieș iremetode. Când sunt implementate corect, tu
ar trebui să fie capabil să folosească cele două clase astfel:

>>> persoană= Person("John",33)


>>> angajat= Employee("Tom",42)
>>> [Link]()
Tom a înregistratîn.

>>> angajat.învârte_afară()
Tom a ieș it din serviciu.

Notă: Trebuie să foloseș ti moș tenirea pentru a implementa clasa angajat.

Întrebare 2
Creează oFormăclasă. Clasa de formă ar trebui să aibă două
attributes: num_sidesș iside_lengthAr trebui să aibă ș i o metodă
apelatafiseaza_tip()

Creează două alte clase:Triunghiș iPentagonFiecare dintre aceste clase ar trebui


moș teniț i dinFormăclasă.

192
AmbeleTriunghiș iPentagonclassele ar trebui să aibăsuprafaț ă()metode.

Când sunt implementate corect, ar trebui să poț i folosi clasele tale ca


urmează:
>>> formă= Formă(7, 2)
>>> shape.arata_tipul()
Eu sunt o formă

>>> triunghi= Triunghi3)# Aceasta se referă la lungimea laturii


>>> triangle.arata_tipul()
Eu sunt un triunghi

>>> [Link]()
3.9
>>> stilou= Penatgon4Aceasta se referă la lungimea laturii
>>> pent.afiseaza_tip()
Sunt un pentagon
>>> [Link]()
27.53

Notă: Triunghiul este un triunghi echilateral ș i pentagonul este regulat


pentagon. Puteț i găsi formulele pentru ambele arii online.

Întrebarea 3
Creează unCeasclasă. Ar trebui să aibă trei atribute:oră, minut, ș ial doilea. Acesta
ar trebui să aibă ș i o metodă numităarată_timp()care afiș ează timpul în format de 24 de ore
timp. De asemenea, ar trebui să aibă o metodă numităbip()care avansează timpul cu 1
al doilea.

Creează unCalendarclasă. Ar trebui să aibă trei atribute:zi, luna, ș ian. Este


ar trebui să aibă două metode, una numităarata_data()ș i celălalt
a fost apelaturmătoare()care avansează data la ziua următoare.

Creează o a treia clasă numităCeasCalendarcare moș teneș te de la


amândouăCeasș iCalendar. Ar trebui să aibă o metodă numităbip()acela
avansează timpul cu 1 secundă, iar o a doua metodă,afiș ează_data_oră() acea
arată data ș i ora.

Când este implementat corect, ar trebui să poț i folosi clasele tale ca


urmează:
193
>>> ceas= Ceas23, 59, 59)
>>> ceas.afiseaza_timpul()
Timpulis23:59:59
>>> [Link]()
>>> ceas.arata_timpul()
Timpulis00:00:00
>>> cal= Calendar30, 12, 2019)
>>> cal.arata_data()
Datais30/12/2019
>>> [Link]()
>>> cal.arata_data()
Data31/12/2019
>>> calClock= CalendarClock31, 12, 2019, 23, 59, 59)
>>> calClock.arata_data_ora()
Data31/12/2019 ș itimpuleste23:59:59
>>> [Link]()
>>> calClock.afiseaza_data_timpul()

Data01/01/2020 ș iorais00:00:00

Notă: Există câteva modalităț i de a completa această întrebare, totuș i vreau să te ...
foloseș te moș tenirea multiplă. Dacă o faci, atunci codul pentru CalendarClock ar trebui să fie
destul de scurt.

194
Capitolul 21 - Structuri de date de bază
Structura de bază a fiecărui software pe care îl vei scrie va consta în două principale
lucruri: date ș i algoritmi. Ș tim că algoritmii sunt utilizaț i pentru a manipula
datele din software-ul nostru (ș i această manipulare ar trebui să fie efectuată ca
eficient cât mai bine posibil). Din acest motiv, este important să ne structurăm datele astfel încât
că algoritmii noș tri pot manipula datele eficient.

Am întâlnit deja diverse structuri de date, liste ș i dicț ionare, ca să numim câteva
puț ini. De asemenea, ș tii că utilizarea listelor, de exemplu, ne face foarte uș or să
stochează ș i manipulează secvenț e de date (Crede-mă, fără această abstractizare,
devine un pic deranjant).
Am văzut de asemenea că structurile de date ne permit să modelăm sistemele pe care le observăm
în lumea reală. De exemplu, am putea proiecta ș i construi o clasă care să ne permită
pentru a modela o bibliotecă. Am putea folosi cu uș urinț ă acest lucru pentru a construi un sistem de gestionare a bibliotecilor

sistem.

În acest capitol vom examina două structuri de date fundamentale care sunt
folosit peste tot în informatică. De asemenea, vom analiza unele exemple de
cum să profiti de ele.

21.1 - Stiva
Stiva este una dintre cele mai fundamentale structuri de date în informatică. Fiecare
de fiecare dată când rulezi un program, acel program profită de un stivă. Mai întâi voi
explică cum funcț ionează, apoi îț i voi explica cum calculatorul tău profită de
ea.

O stivă este o structură de date liniară care urmează un anumit ordin în care
operaț iunile sunt efectuate. O stivă este o structură de date LIFO (Ultimul intrat, primul ieș it).
Adică, ultimul element introdus în stivă este primul element care va
părăseș te stiva. Te poț i gândi la o stivă ca la o stivă de farfurii de cină. Farfuriile sunt
înghesuite, una peste alta. Ultimul farfurie pusă deasupra stivei
va fi prima placa care va fi îndepărtată deoarece nu putem îndepărta placa la
fundul (sau teancul de farfurii s-ar răsturna ș i toate s-ar sparge).
O stivă (în mod obiș nuit) are 4 operaț ii principale: push (adaugă un element în vârf),
pop(remove un element de la vârf), top (arată elementul de la vârf) ș i

195
isEmpty (este stiva goală). De asemenea, putem adăuga o metodă de lungime ș i este de obicei
util!

Aici este o ilustraț ie a unei stive

1.#######
2.# Stiva
3.#######
4.
5.|------| <-- Sus
6.|------|
7.|------|
8.|------|
9.|------|
10.|------|
11.|------|
12.
13.
14.###########
15.# Dacă scoatem:
16.###########
17.
18.|------| <-- Pop
19.
20.|------| <--Vârful nou
21.|------|
22.|------|
23.|------|
24.|------|
25.|------|
26.
27.
28.###############
29.# Dacă împingem
30.# a new element:
31.###############
32.
33.|------| <--Adaugă nou
34.|------| element
35.|------| (nou vârf)
36.|------|
37.|------|
38.|------|
39.|------|
40.|------|

Stiva este o structură de date atât de fundamentală încât multe instrucț iuni ale computerului
seturile oferă instrucț iuni speciale pentru manipularea stivelor. De exemplu, Intel
Procesorul Pentium implementează setul de instrucț iuni x86. Acest lucru permite maș inii
limbaje pentru programatori pentru a programa calculatoarele la un nivel foarte scăzut (Assembly

limbă, de exemplu).
Un tip foarte special de stivă numit "Stiva de apeluri" sau "Stiva de program", de obicei
scurtat la "Stiva" este ceea ce unele dintre instrucț iunile din instrucț iunea x86
set manipulare.

196
Să considerăm ce se întâmplă cu următorul program la un nivel inferior (Pentru
oricine are o înț elegere solidă a calculatoarelor, acesta este un nivel puț in ridicat, dar un
exemplu bun).
.
.
.
print(4)
.
.
.

În snippet-ul de mai sus în Python, avem un set de instrucț iuni care se execută în
ordine (Aș a cum am văzut întotdeauna). La un moment dat, apelăm funcț ia de imprimare pentru
afiș aț i numărul 4 în fereastra noastră de terminal. Aici intervine stiva
în acț iune. Să ne uităm la modul în care programul nostru ar putea fi stocat în memorie (La un nivel înalt

nivel)
Memory Address Instrucț iune
----------------------------------

0x0000001 ....... Codul intern pentru imprimare


funcț ia ar putea
0x0000002 ....... # să fie stocat la 0x0...01 până la 0x0...03.

0x0000003 .......
.
.
.
0x0000004 ....... Câteva instrucț iuni înainte de tipărire.

0x0000005 print(4) Apelul pentru a tipări.

0x0000006 ....... Unele instrucț iuni după imprimare (The


următorul
. # instrucț iune de executat).
.

(SUNT CONȘ TIENT CĂ ACEASTA NU ESTE CE SE ÎNTÂMPLĂ DE FAPT, DAR SĂ MERGEM CU ACEASTA)
DEOCAMDATĂ).

197
Când rulăm un program, acesta este încărcat în memorie ca cod maș ină (Codul
computerul ș tie cum să execute). Instrucț iunile sunt stocate secvenț ial. În aceasta
din perspectiva asta, putem privi funcț iile ca fiind "mini programe" în interiorul programului nostru principal.

Adică, codul pentru ele este stocat în altă parte în memorie. Când noi
apeleazăprint(4)de fapt spunem, sari la locul unde este codul pentru print
începe să execuț i instrucț iunile în mod secvenț ial până când funcț ia este finalizată, apoi
întoarceț i-vă la locaț ia originală ș i continuaț i să executaț i de unde aț i rămas.
Înainte să explic asta, CPU-ul are multe piese speciale de memorie în interiorul său,
numite registre (Acestea sunt ca bucăț i mici de RAM, de obicei de 32 de biț i sau 64 de biț i în
Una dintre aceste registre se numeș te registrul pointerului de instrucț iune, adesea
prescurtat la IP. Conț ine adresa de memorie a următoarei părț i de cod pentru
executa.

În acest caz, executăm instrucț iunea la0x0000004( apoi creș teț i IP-ul), în
următoarea instruire pe care o numimprint(4)care se află la locaț ia0x0000005 însă codul
pentru funcț ia de imprimare este stocată la0x0000001la0x0000003Aici este unde
stiva intră în joc. Ș tim că atunci când tipărim numărul dorit
continuăm de unde am rămas ș i executăm instrucț iunea la0x0000006. În acest caz
împingem adresa de retur (0x0000006) pe stivă, setează IP-ul
spre0x0000001ș i începe să execute codul pentru funcț ia de imprimare. Când suntem
terminat, scoatem adresa de returnare de pe stivă (0x0000006) ș i plasează acest lucru în
IP-ul. Acum programul nostru continuă să ruleze de unde am rămas.
Sunt sigur că îț i poț i imagina cum funcț ionează recursia acum la acest nivel (în esenț ă o
serie de împingeri, împingeri, împingeri ...... scoateri, scoateri, scoateri).

Lucrurile sunt mult mai complexe decât atât, dar nu este necesar pentru a
explicaț ia modului în care stivele sunt utilizate la cele mai fundamentale niveluri. Nu
nu te îngrijora prea mult dacă nu ai înț eles totul. Nu este necesar pentru asta
carte, dar arată doar cât de importantă este stiva.
Stivele au multe utilizări la nivel înalt, de exemplu, mecanismele de anulare în text
editori în care ț inem evidenț a tuturor modificărilor de text într-o stivă. Acestea pot fi folosite
În browsere pentru a implementa un mecanism de mers înapoi/înainte pentru a merge înapoi ș i înainte

între paginile web.

Haideț i să privim codul pentru un stivă în Python. Vom implementa o stivă folosind un
listă

[Link]:

198
2. def__init__(self):
3. [Link] = []
4.
5. defpune(self, elem):
6. [Link](elem)
7.
8. defpop(self):
9. iflen([Link]) == 0:
10. returnNone
11. altfel:
12. [Link]()
13.
14. defisEmpty(self):
15. iflen([Link]) == 0:
16. returneazăAdevărat

17. returneazăFals
18.
19. deftop(self):
20. [Link][-1]

Aceasta este o versiune foarte simplă a unui stivă, dar acum putem folosi stiva noastră ca
urmează:

[Link] = Stack()
2.
[Link](1)
[Link](4)
[Link](2)
6.
[Link]([Link]())
8.
[Link]([Link]())
[Link]([Link]())
[Link]([Link]())

Vom obț ine următorul rezultat dacă rulăm acest program


2sus
2
4
1

Când numimvârf()metodă, nu eliminăm de fapt elementul de top, noi


sunt doar spuse ce este. Când folosimpop()metodă, înlăturăm partea de sus
element.
Vom privi un exemplu în care acest lucru poate fi folosit un pic mai târziu.

21.2 - Coada
Cozile sunt într-un anumit sens similare cu stivele. Ele sunt o structură de date liniare, cu excepț ia
mai degrabă decât ordinea de operare fiind Ultimul intrat, primul ieș it, ele sunt FIFO (Primul intrat)
Primul Ieș ire). Se comportă exact ca orice coadă la care te-ai gândi în viaț a reală. O

199
queue at a supermarket for example, you get in line at the back and wait until
Ajungi la faț ă pentru a pleca.

În informatică, o coadă poate fi utilă în programarea CPU. În computere, există


se întâmplă multe lucruri care par a fi, în acelaș i timp. De exemplu,
poate că ai muzică care să cânte în timp ce citeș ti un articol. Există multe lucruri
se întâmplă aici. Muzica ta este redată, monitorul tău este actualizat
(actualizat) pe măsură ce derulaț i prin articolul dvs. ș i folosiț i mouse-ul
roata pentru a indica când să derulaț i. Într-un sens simplu, CPU-ul dvs. poate gestiona doar
cu câte un lucru pe rând. Aplicatia ta de muzica are nevoie de timp pe CPU pentru a
sortaț i următorul bit de muzică, în timp ce derulaț i, în timp ce acest lucru se întâmplă, mouse-ul dvs.
driverul are nevoie de timp CPU pentru a spune computerului ce să facă, apoi monitorul tău
driverele au nevoie de timp CPU pentru a reîmprospăta pixelii de pe ecranul tău. Totul pare să fie
se întâmplă în acelaș i timp, cu excepț ia cazului în care nu este (computerele sunt pur ș i simplu atât de rapide încât

aparent este). Ce se întâmplă de fapt în această situaț ie este că fiecare program este
folosind rapid CPU-ul, apoi revenind în coadă. Acest lucru se întâmplă peste
ș i din nou. Un algoritm de programare a CPU se ocupă cu programul care primeș te
mergi mai departe pe CPU ș i este posibil să implementeze o variaț ie a unei cozi pentru a gestiona

aceasta. (O coadă de prioritate, de exemplu).

Au metode asemănătoare pentru adăugare ș i eliminare, cu excepț ia faptului că


suntînregistra()ș ieliminare()respectiv.
Cred că ai prins esenț a modului în care poț i vizualiza o coadă, aș a că o să continui doar cu
sari la cod pentru implementarea unei cozi. Din nou, vom implementa o coadă
folosind o listă.

[Link]:
2. def__init__(self):
3. self.q = []
4.
5. defenqueue(self, elem):
6. [Link](elem)
7.
8. defdequeue(self):
9. iflen(self.q) != 0:
10. [Link](0)
11.
12. defisEmpty(self):
13. dacă len(self.q) > 0:
14. returnFalse
15. returneazăAdevărat

Ș i iată. O clasă Queue foarte simplă. Observaț i cum scoatem elemente de la index
0. Amintiț i-vă căpop()metoda pentru liste acceptă un argument opț ional care este
indicele listei din care vrei să elimini un element. Dacă nu furnizăm
200
acest argument opț ional are ca valoare implicită -1 (sfârș itul listei, ceea ce este ceea ce
stacks fac). Aici eliminăm elementul de la începutul listei, dar adăugăm
elemente la sfârș it.

Rulând următorul program, va produce următoarea ieș ire

[Link] = Queue()
2.
[Link](1)
[Link](4)
[Link]ă.intră(2)
6.
[Link]([Link]())
8.
[Link]([Link]())
[Link]([Link]())
[Link]([Link]())
12.
[Link]([Link]())

Fals
1
4
2

Adevărat

21.3 - Exemple
Primul exemplu pe care o să-l analizez este pentru stive. Această întrebare este cunoscută că
au fost solicitate în timpul interviurilor de codare anterioare la Google!

Problema este: Dat un ș ir de intrare constând din paranteze deschise ș i închise


paranteze, scrie un program python care să indice dacă ș irul este
echilibrat.

De exemplu:
([{}])
Echilibrat

(()[])
Desechilibrat

{(){[]}}

201
Echilibrat

Input: [()(){]
Dezechilibrat
O abordare pe care o putem adopta pentru această problemă este să folosim o stivă. Fiecare dată când noi

când întâlnim o paranteză de deschidere, o adăugăm la stivă. Când noi


când întâlnim o paranteză de închidere, scoatem din stivă ș i verificăm că elementul
am scos este paranteza deschisă pentru paranteza închisă. De exemplu,[ este
paranteza de deschidere pentru], similar,{ este paranteza de deschidere pentru} ș i aș a mai departe.

Iată o posibilă soluț ie. Să presupunem că clasa noastră de stivă dinainte există:

[Link] = ["(","[","{"]
2.# Re ț ineț i că pairs este un dic ț ionar care mapează paranteza de închidere
3.# la paranteza de deschidere
[Link] = {")":"(","]":"[","}":"{"}
5.
[Link](input_string):
7. stivă = Stivă()
8. forbracketininput_string:
9. ifbracketinopening:
10. [Link](bracket)
11. [Link]():
12. returnFalse# Nu se poate popa nimic deoarece stiva este goală, deci este dezechilibrată

13. elifpairs[bracket] != [Link]():


14. returnFalse# Parantezele nu s-au potrivit, aș a că este dezechilibrat
15.
16. return [Link]()# Dacă stiva este goală la sfârș it,
17. # întoarce Adevărat, altfel, Fals

Putem folosi mai bine harta perechilor ș i să ne facem codul un pic mai ordonat, dar
nu va fi la fel de uș or de citit, aș a că am ales o abordare puț in mai lungă.

Acum putem rula codul nostru după cum urmează pentru a obț ine rezultatul dorit din
exemplu de intrare ș i ieș ire de mai sus:

1.# CODUL DEASUPRA AICI


2.
[Link] = input()
[Link]ă(balanced(inputString)):
5. Afiș ează("Echilibrat")
[Link]:
7. Imbalansat

Nu am un exemplu de utilizare a cozii, deoarece nu pot să-mi dau seama de nimic util.
fă cu ei cu cunoș tinț ele pe care le avem în acest moment. Nu te îngrijora
totuș i, va fi o întrebare bună despre cozi care va apărea în curând.

202
21.4 - Exerciț ii
Întrebare 1
Îț i sunt date două ș iruriSș iT. Ambele ș iruri conț in caractere alfanumerice
caractere sau un caracter '#'. Un '#' înseamnă ș tergere. Scopul tău este să foloseș ti
cunoaș terea stivelor pentru a proiecta o funcț ie care va decide dacă ambele ș iruri
sunt egale după ce operaț ia de ș tergere a fost aplicată. De exemplu:
S=, T="xw#z"
Output:True
Explicaț ie: Când operaț iunea de ș tergere cu backspaceesteaplicate, ambele ș iruri devin
xz

S="abcd##", T ="acbd##"
Output:False
Explicaț ie: S devine 'ab'ș iT devine 'ac' care suntnuacelaș i

S="z##y", T="#d#y"
Output:True
Ambele ș iruri devin 'y'

S="er##", T="u#u#"
Output: true

Explicaț ie: Ambele Sș iT devin''(ș ir gol)

Întrebarea 2
Este posibil să creezi o coadă prin utilizarea a două stive. Implementează o
clasă de coadă similară cu cea de mai sus, cu excepț ia faptului că nu foloseș te o listă pentru a implementa coada

foloseș ti două stive.


Acesta ar putea fi un pic complicat, va trebui să te gândeș ti la asta.

Întrebarea 3
Este de asemenea posibil să creezi un stivă prin utilizarea a două cozi. Implementează
o clasă de stivă asemănătoare cu cea pe care am văzut-o anterior, cu excepț ia faptului că în loc să folosească o listă pentru

implementează stiva, foloseș te două cozi.

203
Acesta ar putea fi puț in complicat, va trebui să te gândeș ti la asta.

Mini Proiect 1
Trebuie să proiectaț i un calculator RPN. RPN înseamnă Notaț ie Poloneză Inversă.
Un calculator RPN este cunoscut ș i sub numele de calculator postfix. Noi, ca oameni, facem
matematica astfel, de exemplu,4 + 7sau trebuie să folosim regulile BEMDAS:8 + ((10 *
3) / 2). În RPN, am reprezenta acestea ca:4 7+ș i ultima expresie pe care o
reprezentaț i ca8 10 3 2 / * +Ceea ce se întâmplă aici este operatorul (+ este în
poziț ia prefixului în loc de poziț ia infixului, aș a cum suntem obiș nuiț i). Aceasta ar putea părea o
puț in confuz, dar este de fapt destul de simplu ș i putem folosi o stivă pentru a rezolva
această problemă.

Să vedem cum funcț ionează asta:


Expression: 4 7 +
1) Citeș te primul caracter (4)
2) Acesta este un număr, aș a că îl împingem pe stivă

3) Citeș te următorul caracter (7)

4) Aceasta este de asemenea un număr, aș a că îl adăugăm în stivă

5) Citeș te următorul caracter (+)


6) Acesta este un operator. Este un operator binar deoarece funcț ionează pe două
operanzi, aș a că noi

scoate două elemente din stivă


7) Adăugaț i cele două numere împreună

8) Împinge rezultatul înapoi pe stivă

Dacă am avea un operator unar, cum ar fi negarea, atunci am scoate un element.


din stivă, calculează rezultatul ș i împinge-l înapoi.

Trebuie să implementezi următoarele operaț ii în calculatorul tău:

• Adăugare: (+)
• Scădere: (-)
• Înmulț ire*)
• Împărț ire la podea (//)
• Negaren)

• Puteree)

204
Calculatorul tău ar trebui să citească expresii RPN, câte una pe linie ș i
evaluează-le. Există un operator suplimentar de implementat. Acesta estepcare
reprezintă print. Dacă întâlneș tipapoi tipăriț i rezultatul. Puteț i presupunepva
întotdeauna apare la sfârș itul introducerii.

Exemplu:
473++p
14
4+7+3

58*np
-40
-(5 * 8)

361++2ep
Output: 100
(3 + 6 + 1)^2

Reflectaț i cu atenț ie la această problemă. Este chiar un proiect grozav pentru începători să găzduiască.

pe contul tău de Github pentru a-ț i prezenta munca lumii!

205
Capitolul 22 - Date mai avansate
Structuri
În capitolul anterior, am învăț at despre câteva date simple, dar fundamentale.
structuri cu implementări destul de simple. În acest capitol, ne vom
aruncă o privire la câteva structuri de date noi. Ele vor fi, de asemenea, puț in mai
avansate în implementarea lor.

22.1 - Liste înlănț uite

Prima structură de date pe care o vom analiza în acest capitol este o listă înlănț uită.

O listă legată este o structură de date liniară în care fiecare element este un separat.
element. Obiectele listei legate nu sunt stocate în locaț ii contigue. În schimb,
Obiectele listei legate sunt legate între ele folosind pointeri.

Pe parcursul acestei cărț i, este posibil să fi făcut referire la listele Python ca la array-uri ș i invers.

versatil. Listele Python au o implementare complicată în spatele scenei. Aceasta


permite ca listele să fie de dimensiuni arbitrare, să crească ș i să se micș oreze ș i să stocheze multe articole de

diverse tipuri.

În multe alte limbaje de programare, un array este foarte asemănător cu o listă de dimensiune fixă
care stochează elemente de un tip specific. Acestea stochează elemente în mod contiguu în
memorie. Aceasta nu este neapărat cazul în Python.

Python este implementat într-o limbaj numit 'C'. Această limbaj este de nivel scăzut.
comparativ cu Python. În limbajul C, listele Python sunt implementate cu un
o structură de date oarecum similară cu o listă înlănț uită. Este mult mai complicat
decât o listă legată, dar multe dintre conceptele ș i tehnicile pe care le vom învăț a aici vor
aplicaț i la implementarea listelor C Python.

Există multe variaț ii ale listelor legate, dar în acest capitol, vom merge la
Uitaț i-vă la o variaț ie numită Listă Linkedă Simplă.

Mai jos este un diagramă a unei Liste Legate Simplu:

206
Există diverse elemente în acest sens, aș a că permite-mi să explic:

• Capul:Capul este primul element din listă


• Coada: Coada nu este marcată aici, dar este ultimul element (5 în acest caz)
• Un nod constă din două lucruri; datele ș i un pointer către următorul
element (Următorul)

Listelor legate au diverse avantaje faț ă de array-uri (nu listele Python). Acestea
inclusiv dimensiunea dinamică (ele pot creș te ș i micș ora după cum este necesar, la fel ca Python)
liste, în timp ce array-urile nu pot face acest lucru) ș i uș urinț a inserț iei ș i ș tergerii.

Când ș tergem ceva dintr-o listă Python, lista trebuie redimensionată ș i


alte lucruri trebuie să fie făcute (acest lucru se face în spatele scenei, astfel încât noi nu
îngrijorează-te în legătură cu asta).

Există, de asemenea, unele dezavantaje ale listelor legate în comparaț ie cu array-uri. Noi
nu le putem indexa, prin urmare dacă dorim să accesăm un element trebuie să iterăm
prin fiecare element, începând de la cap, în ordinea până găsim
elementul pe care îl căutăm.

Din diagrama de mai sus, putem descompune problema implementării unei liste legate
enumeră două lucruri:

1. O clasă de nod: Aceasta va con ț ine datele pe care nodul le va stoca ș i un pointer
la următorul nod.
2. Clasa Linked List: Aceasta va con ț ine nodul de început ș i metodele pe care le putem utiliza
executaț i pe lista legată.

Să ne uităm la clasa nod:

[Link]:
2. def__init__(self, elem):
3. [Link] = elem
4. [Link] = None

Aceasta este clasa noastră de noduri pentru listă legată. Este foarte simplă ș i conț ine doar două
atributele. Primul este datele pe care nodul le va stoca ș i un atribut anexa.
atributul următor este setat laNiciunulîn mod implicit, deoarece nu va indica spre nimic iniț ial.

207
Acest concept de nod este foarte puternic atunci când vine vorba de structuri de date.
ne oferă multă flexibilitate atunci când dezvoltăm alte structuri de date, după cum vom vedea
mai târziu.

Să ne uităm acum la prima încercare a listei noastre legate:

[Link]:
2. def__init__(self):
3. [Link] = None

Când iniț ializăm noiListalegatăva fi gol, adică, capul va înd indica


la nimic (Nimic). Asta e tot ce avem nevoie pentru a începe implementarea metodelor.

Pentru a incepe, ne vom uita laadauga()metodă. În primul rând, trebuie să ne gândim


despre cum vom proceda pentru a face acest lucru. În lista noastră legată, vom fi
adăugarea de noi elemente la sfârș itul listei. În primul rând, trebuie să verificăm dacă
capul este gol. Dacă este, atunci doar indicămListălegatăîndreaptă-te spre un nou nod.
În caz contrar, trebuie să „urmărim” această cale de indicii către noduri până când unul dintre
nodurilorurmătorulpuncte de atribut pentruNiciunul. When we find this node then we update
esteurmătorulatribut pentru a indica elementul pe care încercăm să-l adăugăm.

Să vedem cum se face asta:


[Link]ăListaÎnlăn ț uită:
2. def__init__(self):
3. [Link] = None
4.
5. defadd(self, elem):
6. [Link] == None:
7. [Link] = Nod(elem)
8. altfel:
9. curr = [Link]
10. [Link] != None:
11. curr = [Link]ător
12. [Link] = Nod(elem)

Aici verificăm că capul listei înlănț uite nu este gol. Dacă este, atunci noi
atribuiț i un nouNodla lista înlănț uităcap. Altfel, creăm o nouă variabilă
apelatcurrAcest lucru ț ine evidenț a nodului pe care ne aflăm. Dacă nu am face asta, am...
ar ajunge să actualizeze lista legatăcapnod din greș eală. După ce creăm
această nouă variabilă, parcurgem elementele listei, mergând de la nod
a se nodi prinurmătorulpointer până găsim un nod al căruiurmătorulpointer-ul este
gol. Când găsim acel nod, îi actualizămurmătorulpointeur pentru a indica la un
nouNod.

208
Acest lucru poate dura puț in timp pentru a-l înț elege sau a-l învârti în minte, dar
cu atât mai mult lucrezi cu structuri de date de acest tip sau asemănătoare, cu atât mai mult are sens.
va face.

Să ne uităm la metoda noastră de ș tergere. Avem multe opț iuni atunci când ș tergem
elemente dintr-o listă legată la fel cum facem cu adăugarea lor. Am putea elimina
primul element, ultimul element sau prima apariț ie a unui element. Din moment ce
lista noastră legată poate conț ine multe apariț ii ale aceleaș i date, vom elimina
prima apariț ie a unui element.

Să vedem cum poate fi făcut acest lucru cu ajutorul unui diagramă:

După cum puteț i vedea, din acest diagramă dorim să ș tergem nodul care conț ine2.
Pentru a face acest lucru, găsim primul nod care esteurmătorulpointer indică către unNodcă
conț ine valoarea2Când găsim astaNodtocmai am actualizaturmătoarepunctator către
indică acelaș i nodNodvrem să ș tergem puncte de asemenea. Practic, noi
redirecț ioneazăurmătorulpunctul de acces pentru a sări peste elementul pe care dorim să-l ș tergem. Acesta este
destul de uș or de făcut.

Hai să vedem cum se face.


[Link]:
2. def__init__(self):
3. [Link] = None
4.
5. def ș terge(self, val):
6. dacă [Link] == None:
7. întoarce
8. dacă [Link] == val:
9. [Link] = [Link]
10. returnval
11.
12. curr = [Link]
13. [Link] != [Link] != val:
14. curr = [Link]ătoare
15.
16. dacă [Link]ător == None:
17. întoarcere
18. altfel:
19. [Link] = [Link]
20. returnval

Trebuie să acoperim câteva cazuri aici. Primul este că lista este goală în
care nu returnează nimic. A doua este că capul listei legate este

209
elementul pe care dorim să-l ș tergem. Dacă este, atunci facem capul listei
al doileaNodîn listă (care poate fiNiciunuldar e în regulă, înseamnă doar lista
doar a avut un singur articol). În cele din urmă, dacă nu este niciunul dintre aceste cazuri, parcurgem lista

utilizăm căutarea liniară până când găsim prima apariț ie a elementului, apoi noi
redirecț ionaț iurmătorulpointerul deNodcare indică cătreNodvrem să
ș terge, cătreNodethenextpunctul deNodvrem să ș tergem punctele de asemenea.

Acea ultimă parte ar putea părea confuză, dar facem ceea ce vezi în
diagram. Probabil că este cel mai bine în acest moment, dacă eș ti confuz de acest lucru, să desenezi asta
scenariul pe hârtie pentru a ajuta la clarificarea lucrurilor.

Există câteva alte metode utile pe care le putem adăuga aici, dar le vom lăsa
pentru mai târziu.

Chiar înainte să termin cu listele legate, vreau să vorbesc puț in mai mult despre
complexităț ile metodelor lor ș i de ce ai putea să le foloseș ti (sau nu).

Complexitatea timpului de rulare a metodei add este O(n) în acest caz, deoarece trebuie să
iteraț i peste fiecare intrare din listă pentru a găsi ultimul element. Timpul de execuț ie
complexitatea metodei de ș tergere este de asemenea O(n). Deș i nu întotdeauna
iteraț i peste fiecare element din listă, Big-O se ocupă de cel mai grav caz, care este
trecând prin întreaga listă. Există optimizări pe care le-am putea face totuș i
ș i vom ajunge la ele mai târziu.

Listele legate în Python de obicei nu au un caz de utilizare. Acest lucru se datorează faptului că Python
listelor sunt deja foarte bine optimizate ș i dinamice. Cu toate acestea, în limbile precum
ca C sau C++, Listele Înlănț uite sunt esenț iale (Unde tablourile dinamice, cum ar fi listele python,
s-ar putea să nu existe). De asemenea, apar în interviurile tehnice, aș a că este cel mai bine să ș tiț i
Ei. De fapt, dacă aș angaja un inginer, aș fi foarte sceptic în privinț a angajării unuia
cine nu ș tia să codeze o listă legată.

22.2 - Arbori de Căutare Binari (BST-uri)

Înainte de a începe această secț iune, vreau să îț i fac o avertizare. Vom folosi
recursie destul de mult aici. Dacă recursia nu este punctul tău forte (ceea ce este...
probabil nu voi fi în acest punct), poate să revizuiască partea de recursie.
Cu toate acestea, această secț iune ar putea fi un loc bun pentru a te ajuta să înț elegi
recursie. Arborii binari de căutare (BST) m-au ajutat să înț eleg recursia (bine, la
cel puț in atunci când recursia a început să aibă sens pentru mine).

210
Un arbore de căutare binară (BST) este oarecum diferit de structurile de date pe care le
am întâlnit până acum. Nu este o structură de date liniare. Este un tip de date ordonate
structură care stochează elemente. BST-urile permit căutări rapide, adăugări ș i eliminări
de obiecte. BST-urile îș i păstrează obiectele în ordine sortată astfel încât operaț iile care pot fi
sunt rapide, spre deosebire de o listă înlănț uită al cărei adăugare ș i eliminare
operaț iile sunt O(n). Operaț iile de adăugare ș i eliminare pe un BST sunt O(log n).
Căutarea într-un BST este, de asemenea, O(log n). Acesta este cazul mediu pentru cele trei.
operaț iuni.

Aceasta este o situaț ie similară cu căutarea liniară versus căutarea binară pe care am analizat-o.
mai devreme.

În informatică, un 'arbore' este un tip de date abstract utilizat pe scară largă.


definit de comportamentul său, nu de implementare, care simulează un arbore ierarhic
structură (asemănătoare cu un arbore genealogic), cu un nod rădăcină ș i subarbori de copii
cu un nod părinte reprezentat ca un set de noduri interconectate.

O arbore binar este un tip de arbore în care fiecare Nod din arbore are cel mult două
noduri copil. Un arbore de căutare binar este un tip special de arbore binar în care
elementele sunt ordonate. Un diagramă ar putea să te ajute să vizualizezi acest lucru, aș a că iată una:

Există multe de înț eles aici, aș a că lăsaț i-mă să explic. Rădăcina acestui copac este nodul
care conț ine elementul10. Lucrul mare etichetatSub Arboreeste sub drept
arborele nodului rădăcină.

10este nodul părinte către22ș i5 ș i în mod similar,5este un nod copil al10.

Un nod frunză este un nod care nu are copii.

211
Capitolul 21 - Structuri de date de bază
Structura de bază a fiecărui software pe care îl vei scrie va consta în două principale
lucruri: date ș i algoritmi. Ș tim că algoritmii sunt utilizaț i pentru a manipula
datele din software-ul nostru (ș i această manipulare ar trebui să fie efectuată ca
eficient cât mai bine posibil). Din acest motiv, este important să ne structurăm datele astfel încât
că algoritmii noș tri pot manipula datele eficient.

Am întâlnit deja diverse structuri de date, liste ș i dicț ionare, ca să numim câteva
puț ini. De asemenea, ș tii că utilizarea listelor, de exemplu, ne face foarte uș or să
stochează ș i manipulează secvenț e de date (Crede-mă, fără această abstractizare,
devine un pic deranjant).
Am văzut de asemenea că structurile de date ne permit să modelăm sistemele pe care le observăm
în lumea reală. De exemplu, am putea proiecta ș i construi o clasă care să ne permită
pentru a modela o bibliotecă. Am putea folosi cu uș urinț ă acest lucru pentru a construi un sistem de gestionare a bibliotecilor

sistem.

În acest capitol vom examina două structuri de date fundamentale care sunt
folosit peste tot în informatică. De asemenea, vom analiza unele exemple de
cum să profiti de ele.

21.1 - Stiva
Stiva este una dintre cele mai fundamentale structuri de date în informatică. Fiecare
de fiecare dată când rulezi un program, acel program profită de un stivă. Mai întâi voi
explică cum funcț ionează, apoi îț i voi explica cum calculatorul tău profită de
ea.

O stivă este o structură de date liniară care urmează un anumit ordin în care
operaț iunile sunt efectuate. O stivă este o structură de date LIFO (Ultimul intrat, primul ieș it).
Adică, ultimul element introdus în stivă este primul element care va
părăseș te stiva. Te poț i gândi la o stivă ca la o stivă de farfurii de cină. Farfuriile sunt
înghesuite, una peste alta. Ultimul farfurie pusă deasupra stivei
va fi prima placa care va fi îndepărtată deoarece nu putem îndepărta placa la
fundul (sau teancul de farfurii s-ar răsturna ș i toate s-ar sparge).
O stivă (în mod obiș nuit) are 4 operaț ii principale: push (adaugă un element în vârf),
pop(remove un element de la vârf), top (arată elementul de la vârf) ș i

195
[Link]:
2. def__init__(self):
3. [Link] = None
4.
5. defcăutare(self, valoare):
6. returnself.recursive_search([Link], valoare)
7.
8. def cautare_recursiva(self, nod, valoare):
9. dacă nodul este None sau [Link] == valoare:
10. nod de returnare
11. dacă valoarea < [Link]:
12. returnself.recursive_search([Link]ânga, valoare)
13. altfel:
14. returnself.recursive_search([Link], valoare)

Acest lucru poate părea puț in ciudat, deoarece avem două funcț ii de căutare, dar există un motiv bun.

motivul pentru asta. Thecăutaremetoda ne permite să apelăm lacercetare_recursivămetodă


ș i treceț i în nodul rădăcină, în acest fel, acum avem o 'copie' a nodului rădăcină
ș i nu nodul rădăcină în sine, astfel încât să nu ajungem într-o buclă infinită când
cercetare recursivă. Din nou, natura recursivă a acestui lucru este foarte dificil de
explică ca aș încerca să lucrez printr-un exemplu pe hârtie pentru a ajuta la clarificare după
următoarea explicaț ie.

Inside thecăutare_recursivămetoda avem un caz de bază care verifică dacă am


atinsNiciunul(nu am găsit ceea ce căutam) sau am ajuns
celNodcare conț ine ceea ce căutăm.

Dacă nu trecem de cazul nostru de bază, atunci verificăm dacă valoarea pe care o căutăm este
mai mic decât valoarea nodului la care ne aflăm în prezent; dacă da, atunci căutăm în stânga
subarborele acelui nod apelând lacercetare_recursivămetoda ș i trecerea
nodi curenț istângacopac. Altfel, valoarea pe care o căutăm este mai mare
decât valoarea nodului curent, caz în care numimcautare_recursivaș i
treceț i în nodurile curentedreptcopac.

Aminteș te-ț i că arborele stâng sau drept al unui nod este pur ș i simplu un pointer către un nod (putem privi

la acest nod ca nodul rădăcină al unui subarbore).

De exemplu, dacă căutăm valoarea15în copacul din diagramă


deasupra, atunci calea pe care o urmăm arată astfel:

213
Pentru a clarifica, un nod frunzăstângaș iright «copacii» suntNiciunul.

Următorul pas va fi să examinăm inserarea unui element în arbore. Ceea ce facem aici
este practic acelaș i lucru pe care l-am făcut cu căutarea, cu excepț ia cazului în care noi
ajunge la un nod frunză pe calea noastră, vom seta pointerul său stâng sau drept pentru a indica către o
nod nou (în funcț ie de dacă valoarea este mai mică sau mai mare decât
valoarea de la nodul copil).

Iată cum vom aborda asta:

• Caz de bază: Dacă nodul în care ne aflăm esteNiciunulatunci inseraț i noul nod aici.
• Caz recursiv:
• Dacă valoarea pe care o introducem este mai mică decât valoarea nodului curent
apoi verificăm dacă arborele din stânga al nodului curent esteNiciunulDacă este, atunci inserează
acolo, altfel, apelează din nou insert ș i trece subarborele stâng.
• Dacă valoarea pe care o inserăm este mai mare decât valoarea nodului curent
apoi verificăm dacă subarborele drept al nodului curent esteNiciunulDacă este, atunci
inserează acolo, altfel, apelează din nou insert ș i trece subarborele drept.

214
Iată cum se face asta:

[Link]:
2. def__init__(self):
3. [Link] = None
4.
5. definsert(self, val):
6. dacă rootul este None:
7. [Link] = Nod(val)
8. altfel:
9. self.recursive_insert([Link], val)
10.
11. def inserare_recursiva(self, nod, val):
12. dacă val < [Link]:
13. dacă [Link]ânga este Niciunul:

14. [Link] = Nod(val)


15. altfel:
16. self.recursive_insert([Link], val)
17. în caz contrar:
18. dacă [Link] esteNiciunul:

19. [Link] = Nod(val)


20. altfel:
21. self.recursive_insert([Link], val)

Asta e. Sper că poț i vedea de ce recursia este utilă aici. Face codul nostru
citim mai bine ș i când ne planificăm asta în minț ile noastre, se potriveș te în mod natural în
algoritmul nostru.

Următorul, ne vom uita la ș tergerea unui element. Acest lucru este mult mai dificil.
În cazul inserț iei, întotdeauna inserăm într-unul dintre nodurile frunză, dar dacă ș tergem
ceva, apoi apar trei posibilităț i. Prima este cea mai simplă situaț ie:

1. Nodul pe care îl eliminăm nu are noduri fiică (adică un nod frunză). În acest
în acest caz, putem pur ș i simplu să eliminăm nodul.

2. Cazul următor este când eliminăm un nod care are doar un copil.
Din nou, acest lucru este suficient de simplu de gestionat. În acest caz, pur ș i simplu tăiem
nodul pe care îl eliminăm din arbore ș i conectăm copilul său la părintele său.

215
3. Cazul final este atunci când eliminăm un nod care are doi copii.
Acesta este cel mai complex caz ș i necesită o gândire inteligentă. Acolo
totuș i, există o proprietate utilă a BST-urilor pe care o putem folosi pentru a rezolva acest lucru

problemă. Adică, aceeaș i set de valori poate fi reprezentat ca diferit


arbori binari de căutare. Să luăm în considerare următorul set de valori: {9, 23, 11,
30}. Putem reprezenta asta în două moduri diferite:

Ambele aceste copaci sunt diferite, dar ambele sunt valide. Ce am făcut aici
cum să transformi primul copac în al doilea?

• Am început de la nodul rădăcină (9 în acest caz).


• A căutat în subarborele drept pentru elementul minim (11 în acest caz)
• Înlocuit 9 cu 11
• Atârnă 9 din subarborele stâng

Putem lua această idee ș i o putem aplica pentru eliminarea elementelor cu doi noduri copil.
Iată cum vom face asta:

• Găsiț i nodul pe care dorim să-l ș tergem


• Găsiț i elementul minim în subarborele drept

216
• Înlocuiț i elementul nodului care trebuie eliminat cu minimul pe care îl avem.
doar găsit.
• Ai grijă! Subarborele drept conț ine acum un duplicat.
• Aplicaț i în mod recursiv eliminarea pe subarborele din dreapta

Când se aplică eliminarea în subarborele din dreapta pentru a elimina duplicatul, noi
poate fi sigur că nodul duplicat va cădea sub cazurile 1 sau 2. Nu va cădea
în cazul 3 (Nu ar fi fost minimul dacă am fi făcut-o).

Există două funcț ii de care avem nevoie aici. Una este metoda de eliminare ș i
altele vor găsi nodul minim. Aici avem o funcț ie liberă (vom avea
aminoperaț ie pe BST-ul nostru!).

Iată cum să îl codifici, voi comenta ș i codul deoarece este puț in complex:

[Link]:
2. def__init__(self):
3. [Link] = None
4.
5. defremove(self, value):
6. returnself.recursive_remove([Link], None, valoare)
7.
8. defrecursive_remove(self, node, parent, value):
9. # Funcț ie de ajutor
10. defmin_node(nod):
11. curr = nod
12. [Link] != Niciunul:
13. curr = [Link]ânga
14. returncurr
15.
16. # Caz de bază (elementul nu există în arbore)
17. ifnode == None:
18. nodde întoarce
19.
20. Dacă elementul de eliminat este mai mic decât nodul curent
21. atunci este în subarborele stâng. Trebuie să setăm curentul
22. subarborele stâng al nodului este egal cu rezultatul eliminării
23. dacă valoare < [Link]:
24. [Link] = self.recursive_remove([Link], node, value)
25.
26. Dacă elementul de eliminat este mai mare decât nodul curent
27. atunci este în subarborele din dreapta. Trebuie să setăm elementul curent
28. subarborele drept al nodului este egal cu rezultatul eliminării
29. elifvalue > [Link]:
30. [Link] = self.recursive_remove([Link], node, value)
31.
32. Dacă elementul de eliminat este egal cu valoarea lui
33. nodul curent, atunci acesta este nodul de eliminat
34. altfel:
35. print([Link], notparentisNone)
36. Nu este nodul rădăcină
37. dacă nu părinte este None:
38. Nodul nu are copii (CAZUL 2)
39. dacă node.num_children() == 0:
40. daca [Link] == nod:
41. pă[Link] = Niciunul
42. altfel:

217
43. pă[Link] = None
44. Nodul are doar un copil (CAZUL 2)
45. elifnode.num_children() == 1:
46. Obț ine nodul fiu
47. dacă [Link]ânga != Niciunul:
48. child = [Link]
49. altfel:
50. copil = [Link]
51.
52. Indicaț i nodul părinte către nodul copil al
53. nodo pe care îl eliminăm
54. dacă pă[Link]ânga == nod:
55. pă[Link]ânga = copil
56. altfel:
57. [Link] = copil
58.
59. Nodul are doi copii (CAZUL 3)
60. elifnode.num_children() == 2:
61. Obț ine nodul minim în subarborele drept al nodului de ș ters
62. smallest_node = min_node([Link])
63.
64. Copiaț i valoarea celor mai mici noduri în nodul care deț inea anterior
65. valoarea pe care voiam să o ș tergem
66. [Link] = smallest_node.elem
67. self.recursive_remove(node, părinte, valoare)
68. Nodul de ș ters este nodul rădăcină
69. altfel:
70. Numai 1 element în copac (rădăcina) - setează rădăcina la Niciunul
71. ifnode.num_children() == 0:
72. node = None
73. Rădăcina are un singur copil - fă-l pe acesta rădăcină
74. elifnode.num_children() == 1:
75. dacă [Link]ânga != None:
76. [Link] = [Link]
77. dacă [Link] != None:
78. [Link] = [Link]
79. elifnode.num_children() == 2:
80. smallest_node = min_node([Link])
81. [Link] = cel mai mic_node.elem
82. self.recursive_remove(node, None, valoare)
83. nodde întoarcere

Asta e greu. Asigură-te că înț elegi operaț iunea de ș tergere, chiar dacă aia
înseamnă să treci prin asta din nou ș i din nou. Foloseș te un pix ș i o foaie dacă ai nevoie!
Este o întrebare bună de pus de un angajator, deoarece arată cum cineva
abordează o problemă dificilă (subliniind diferite scenarii, descompunând
problemă jos, etc.).

Asta este tot ce vreau să discut despre Arborii de Căutare Binari pentru moment. Există câteva
mai multe metode pe care le putem adăuga, ș i voi lăsa asta în seama ta în exerciț ii!

22.3 - Exerciț ii
Important: Unele dintre aceste exerciț ii sunt destul de dificile! Folosiț i-o pentru a rezolva problemele.
solving techniques to help you arrive at a solution. Sketching out what's
ce se întâmplă pe hârtie este o modalitate bună de a te ajuta!

218
E vremea să ridicăm un pic nivelul de dificultate al întrebărilor. Există
niș te întrebări foarte dificile aici. Mult noroc!

Întrebare 1
Am vorbit mai devreme despre complexităț ile de timp de execuț ie ale metodelor listei legate.
am implementat. Am menț ionat că am putea îmbunătăț i complexităț ile lor.

În prezent, adauga()metoda are o complexitate de rulare de O(n).

Schimbă implementareaadauga()metodă astfel încât să fie timpul de execuț ie


complexitatea este O(1).

Întrebarea 2
Schimbă implementarea luiadaugă()sauș terge() metodele pe Linked
Listă de clasă pentru a obț ine o listă înlănț uită care se comportă ca:

•O stivă
• O coadă

Încercaț i să oferiț i implementări optimizate deadauga()ș i/saueliminare()când faci


acesta.

Întrebare 3
O altă metodă utilă pe care clasa noastră Linked List ar putea să o aibă este olungime()metodă.
Adică, returnează numărul de elemente din lista legată.

Implementaț ilungime()metodă.

Întrebarea 4
Dacă ai gândit cu atenț ie despre implementarea ta alungime()metodă
dacă ai lucrat la exerciț iul anterior, atunci s-ar putea să poț i să sări peste această întrebare.
Cu toate acestea, nu mă aș tept că ai făcut-o.

Dacă presupunerea mea este corectă, a talungime()metoda


iterează peste fiecare element din
listă, adăugând1la lungimea ta de fiecare dată până ajungi la sfârș itul listei. Aceasta
îț i voi dalungime()metodă cu o complexitate de timp de execuț ie O(n).

Putem face mai bine decât atât. Cum ai putea schimba Lista Lincată
clasa astfel încât complexitatea de rulare a talungime()metoda este O(1)?

219
Întrebarea 5
Înălț imea (adâncimea) unui copac este numărul de muchii de pe cel mai lung drum de la
nodul rădăcină la nodul frunză. (O muchie este practic săgeț ile din diagrama noastră
pe care l-am analizat anterior)

{"text":"De exemplu, înălț imea următorului copac este 3"}

Înălț imea este determinată de numărul de muchii din cea mai lungă cale, ca ș i cum ar fi
următoarele

220
Puteț i de asemenea să vizualizaț i înălț imea unui copac astfel:

Ar trebui să scrii o metodă recursivă pentru a găsi înălț imea oricărei binare date.
arbore de căutare

Întrebarea 6
Această întrebare este foarte dificilă

Consideraț i ce se întâmplă atunci când adăugăm elemente în arbore în următoarea


comandă: {2, 5, 7, 12, 13}. Ajungem la o listă legată. Asta înseamnă că
căutarea ș i inserț ia nu mai sunt O(log n). Acum sunt O(n). Acesta nu este chiar atât de grozav
pentru noi.

Putem, totuș i, să facem o optimizare a arborilor noș tri de căutare binară astfel încât
căutarea ș i inserarea sunt întotdeauna O(log n), indiferent de ordinea în care introducem
elemente.

Optimizarea este că diferenț a dintre înălț imea stângă ș i dreaptă


subarborile nu sunt mai mari de unu pentru toate nodurile. Când diferenț a dintre stânga
ș i înălț imea subarborilor din dreapta nu este mai mare decât1spunem că arborele este echilibrat.
Acest lucru înseamnă că, dacă inserăm sau eliminăm un element, iar înălț imea dintre stânga ș i
dacă subarborii din dreapta devin mai mari decât 1, atunci trebuie să reorganizăm nodurile.

Această optimizare înseamnă că arborele nostru de căutare binar va deveni auto-


echilibrare.

Acest tip de arbore binar de căutare auto-echilibrat are un nume special. Se numeș te
un arbore AVL.

Aminteș te-ț i: Această întrebare este foarte dificilă, nu mă aș tept să poț i.


răspunde la aceasta, dar te încurajez să încerci!

221

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