Pregătirea pentru Interviurile Python: Întrebări și Răspunsuri Esențiale
Te afli în pragul unui interviu tehnic Python sau vrei doar să îți verifici cunoștințele? Nicio problemă! Acest articol este creat special pentru a te ajuta să înțelegi mai bine tipurile de întrebări pe care le-ai putea întâlni și, totodată, să îți evaluezi abilitățile Python. Asigură-te că încerci să răspunzi la fiecare întrebare înainte de a verifica soluția, pentru o autoevaluare cât mai corectă. Să începem!
Acest ghid este structurat pe secțiuni tematice, fiecare concentrându-se pe un anumit aspect al limbajului Python. Vei găsi întrebări și răspunsuri detaliate, care te vor ajuta să îți aprofundezi înțelegerea și să te pregătești eficient. Îți recomandăm să adaptezi răspunsurile cu propriile cuvinte, păstrând același sens, pentru a demonstra autenticitate și a evita impresia de răspuns memorat.
Fundamentele Limbajului Python
#1. Ce este limbajul Python?
Python este un limbaj de programare interpretat, de nivel înalt, conceput pentru a fi ușor de citit și de utilizat. Flexibilitatea sa permite dezvoltarea unei game largi de aplicații, de la aplicații web la soluții de inteligență artificială și știință a datelor, fiind popular datorită resurselor vaste oferite de biblioteci și cadre de lucru terțe.
#2. Care este diferența cheie între un interpret și un compilator?
Un interpret procesează și execută instrucțiunile linie cu linie, traducându-le în cod mașină pe măsură ce se derulează programul. Un compilator, în schimb, traduce întregul cod sursă într-un cod mașină executabil într-o singură etapă.
#3. Python este un limbaj tipizat static sau dinamic?
Python este un limbaj tipizat dinamic, ceea ce înseamnă că tipul unei variabile este verificat în timpul rulării programului și nu în timpul compilării.
#4. Ce înseamnă „limbaj tipizat dinamic”?
Într-un limbaj tipizat dinamic, tipurile variabilelor sunt verificate în timp ce codul se execută. Exemple de astfel de limbaje includ Python, JavaScript și Ruby.
Bonus: Limbajele tipizate static, cum ar fi C++, C și Java, verifică tipurile de variabile în timpul procesului de compilare, impunând declararea explicită a tipurilor.
#5. Enumerați câteva aplicații ale limbajului Python.
Python se remarcă prin simplitatea sintaxei și ușurința învățării, ceea ce îl face accesibil chiar și pentru începători. Comunitatea extinsă de dezvoltatori contribuie la un ecosistem bogat de biblioteci și pachete, care acoperă diverse domenii de dezvoltare software, inclusiv aplicații web, GUI, și CLI.
Automatizarea este o altă zonă în care Python strălucește, fiind ideal pentru crearea de scripturi care gestionează sarcini repetitive, precum curățarea discului, trimiterea de e-mailuri sau colectarea datelor despre prețuri.
Nu în ultimul rând, Python joacă un rol esențial în știința datelor, datorită capabilităților sale avansate de analiză și vizualizare a datelor.
#6. Ce tipuri de aplicații ai dezvoltat folosind Python?
Personal, am creat diverse scripturi de automatizare pentru a simplifica sarcinile repetitive și pentru a extrage informații despre prețuri și disponibilitatea produselor.
De asemenea, am utilizat cadre web precum Django și Flask pentru dezvoltarea de aplicații web, dobândind experiență în ambele platforme.
Notă: Acesta este un exemplu de răspuns. Experiențele tale pot fi diferite. Încearcă să descrii proiectele pe care le-ai realizat și, dacă este posibil, oferă exemple concrete.
Tipuri de Date în Python
#7. Care sunt tipurile de date predefinite în Python?
Python oferă o varietate de tipuri de date, printre care se numără `int` (întregi), `float` (numere cu virgulă mobilă), `complex` (numere complexe), `bool` (booleeni), `list` (liste), `tuple` (tuple), `set` (seturi), `dict` (dicționare) și `str` (șiruri de caractere).
Notă: Nu este necesar să enumeri toate tipurile de date. Poți menționa câteva dintre cele mai utilizate și să aștepți ca intervievatorul să ceară mai multe detalii.
#8. Care este diferența dintre o listă și un tuplu?
Atât listele cât și tuplele sunt folosite pentru a stoca colecții de obiecte, dar principala diferență este că listele sunt mutabile, adică pot fi modificate după creare, în timp ce tuplele sunt imutabile.
#9. Ce înseamnă tipuri de date mutabile și imutabile?
Tipurile de date mutabile permit modificări ale conținutului după ce sunt create. Exemple de obiecte mutabile în Python includ listele, seturile și dicționarele.
Tipurile de date imutabile, pe de altă parte, nu permit modificarea valorii lor odată ce au fost create. Șirurile de caractere și tuplele sunt exemple de obiecte imutabile în Python.
#10. Explică câteva metode specifice listelor.
1. **append()**: Această metodă adaugă un element la sfârșitul listei.
>>> a = [1, 2] >>> a.append(3) >>> a [1, 2, 3]
2. **pop()**: Metoda pop() elimină un element din listă. Fără argument, elimină ultimul element, iar cu argument elimină elementul de la indexul specificat.
>>> a = [1, 2, 3, 4, 5] >>> a.pop() 5 >>> a [1, 2, 3, 4] >>> a.pop(1) 2 >>> a [1, 3, 4]
3. **remove()**: Metoda remove() elimină prima apariție a elementului specificat din listă.
>>> a = [1, 2, 2, 3, 4] >>> a.remove(2) >>> a [1, 2, 3, 4]
4. **sort()**: Metoda sort() sortează elementele listei în ordine crescătoare sau descrescătoare.
>>> a = [3, 2, 4, 1] >>> a.sort() >>> a [1, 2, 3, 4] >>> a.sort(reverse=True) >>> a [4, 3, 2, 1]
5. **reverse()**: Metoda reverse() inversează ordinea elementelor din listă.
>>> a = [3, 2, 4, 1] >>> a.reverse() >>> a [1, 4, 2, 3]
Notă: Există și alte metode, cum ar fi `insert`, `clear`, `count`, etc. Nu este nevoie să le explici pe toate. Concentrează-te pe cele pe care le folosești frecvent.
#11. Explică câteva metode specifice șirurilor de caractere.
1. **split()**: Metoda split() împarte un șir de caractere în funcție de un delimitator și returnează o listă. Dacă nu se specifică un delimitator, împarte șirul la spații.
>>> a = "Acesta este un exemplu." >>> a.split() ['Acesta', 'este', 'un', 'exemplu.'] >>> a = "1, 2, 3, 4, 5, 6" >>> a.split(", ") ['1', '2', '3', '4', '5', '6']
2. **join()**: Metoda join() unește o listă de șiruri de caractere, folosind un anumit delimitator.
>>> a = ['Acesta', 'este', 'un', 'exemplu.'] >>> ' '.join(a) 'Acesta este un exemplu.' >>> ', '.join(a) 'Acesta, este, un, exemplu.'
Notă: Alte metode importante includ `capitalize()`, `isalnum()`, `isalpha()`, `isdigit()`, `lower()`, `upper()`, `center()`, etc.
#12. Ce este indexarea negativă în liste?
Indexarea este utilizată pentru a accesa elementele dintr-o listă. Indexarea obișnuită începe de la 0.
Indexarea negativă permite accesarea elementelor începând de la sfârșitul listei. Ultima poziție este -1, penultima -2, și așa mai departe.
>>> a = [1, 2, 3, 4, 5] >>> a[-1] 5 >>> a[-3] 3 >>> a[-5] 1
#13. Explică câteva metode specifice dicționarelor.
1. **items()**: Metoda `items()` returnează o listă de tupluri, fiecare tuplu conținând o pereche cheie-valoare din dicționar.
>>> a = {1: 'unu', 2: 'doi', 3: 'trei'} >>> a.items() dict_items([(1, 'unu'), (2, 'doi'), (3, 'trei')])
2. **pop()**: Metoda `pop()` elimină din dicționar perechea cheie-valoare corespunzătoare cheii specificate și returnează valoarea.
>>> a = {1: 2, 2: 3} >>> a.pop(2) 3 >>> a {1: 2}
Notă: Alte metode includ `get()`, `keys()`, `values()`, `clear()`, etc.
#14. Ce este felierea (slicing) în Python?
Felierea (slicing) este utilizată pentru a extrage o secțiune (subșir sau sublistă) dintr-un tip de date secvențial. Returnează un nou obiect de același tip cu cel original.
Felierea acceptă trei argumente: indicele de început, indicele de sfârșit și pasul. Sintaxa este `variabila[start:end:step]`. Toate argumentele sunt opționale.
>>> a = [1, 2, 3, 4, 5] >>> a[:] [1, 2, 3, 4, 5] >>> a[:3] [1, 2, 3] >>> a[3:] [4, 5] >>> a[0:5:2] [1, 3, 5]
#15. Care tipuri de date permit felierea?
Felierea poate fi aplicată listelor, tuplelor și șirurilor de caractere.
#16. Ce sunt operatorii de despachetare (unpacking) în Python? Cum se utilizează?
Operatorii `*` și `**` sunt operatori de despachetare în Python.
Operatorul `*` este folosit pentru a atribui mai multe valori din tipurile de date secvențiale unor variabile.
>>> items = [1, 2, 3] >>> a, b, c = items >>> a 1 >>> b 2 >>> c 3 >>> a, *b = items >>> a 1 >>> b [2, 3]
Operatorul `**` este folosit cu dicționare. În principal, el este utilizat pentru a copia elemente cheie-valoare dintr-un dicționar în altul.
>>> a = {1:2, 3:4} >>> b = {**a} >>> b {1: 2, 3: 4} >>> c = {3:5, 5:6} >>> b = {**a, **c} >>> b {1: 2, 3: 5, 5: 6}
Notă: Pentru mai multe informații, puteți consulta documentația oficială despre operatorii de despachetare.
Condiții și Bucle
#17. Python are instrucțiuni switch?
Nu, limbajul Python nu are instrucțiuni `switch`.
#18. Cum poți implementa funcționalitatea instrucțiunilor switch în Python?
Funcționalitatea `switch` poate fi implementată folosind instrucțiunile `if` și `elif`.
>>> if a == 1: ... print(...) ... elif a == 2: ... print(....)
#19. Ce sunt instrucțiunile `break` și `continue`?
**`break`**: Instrucțiunea `break` este folosită pentru a termina executarea unei bucle. Execuția codului continuă cu instrucțiunea de după buclă.
>>> for i in range(5): ... if i == 3: ... break ... print(i) ... 0 1 2
**`continue`**: Instrucțiunea `continue` este folosită pentru a omite execuția codului rămas într-o iterație curentă și a trece la următoarea iterație a buclei.
>>> for i in range(5): ... if i == 3: ... continue ... print(i) ... 0 1 2 4
#20. Când este executat codul din blocul `else` al buclelor `while` și `for`?
Codul din blocul `else` este executat după ce toate iterațiile buclei au fost completate cu succes. Acesta nu se execută dacă bucla este întreruptă cu o instrucțiune `break`.
#21. Ce sunt înțelegerile de liste (list comprehensions) și dicționare (dictionary comprehensions)?
Înțelegerile de liste și dicționare sunt metode concise de a crea liste și dicționare folosind o sintaxă specifică asemănătoare buclelor `for`.
>>> a = [i for i in range(10)] >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a = {i: i + 1 for i in range(10)} >>> a {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}
#22. Cum funcționează funcția `range()`?
Funcția `range()` generează o secvență de numere între un punct de start și un punct de oprire, cu un pas specificat. Sintaxa este `range(start, stop[, step])`. Parametrul `stop` este obligatoriu, `start` și `step` fiind opționale (valorile implicite sunt 0 și, respectiv, 1).
>>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(range(1, 10)) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(range(1, 10, 2)) [1, 3, 5, 7, 9]
Funcții
#23. Ce sunt parametrii și argumentele?
Parametrii sunt numele variabilelor specificate în definiția unei funcții, care acționează ca locuri rezervate pentru valorile ce vor fi primite.
Argumentele sunt valorile actuale transmise funcției în momentul apelării acesteia.
#24. Care sunt diferitele tipuri de argumente în Python?
Python suportă patru tipuri de argumente: argumente poziționale, argumente implicite, argumente cheie și argumente arbitrare.
**Argumente poziționale**: Sunt argumentele normale definite într-o funcție și sunt necesare la apelarea funcției.
>>> def aduna(a, b): ... return a + b ... >>> aduna(1, 2) 3 >>> aduna(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: aduna() missing 1 required positional argument: 'b'
**Argumente implicite**: În definiția funcției, poți da valori implicite argumentelor. Dacă utilizatorul nu specifică valori pentru acestea la apelare, se vor folosi valorile implicite.
>>> def aduna(a, b=3): ... return a + b ... >>> aduna(1, 2) 3 >>> aduna(1) 4
**Argumente cheie**: La apelarea unei funcții, poți specifica argumentele folosind numele lor și valoarea corespunzătoare, ceea ce permite o flexibilitate mai mare în ordinea argumentelor.
>>> def aduna(a, b): ... print("a ", a) ... print("b ", b) ... return a + b ... >>> aduna(b=4, a=2) a 2 b 4 6
**Argumente arbitrare**: Sunt folosite când nu știi de la început câte argumente va primi o funcție. Operatorul `*` colectează argumentele într-un tuplu, iar `**` într-un dicționar.
>>> def aduna(*args): ... return sum(args) ... >>> aduna(1, 2, 3, 4, 5) 15 >>> def argumente_dict(**kwargs): ... print(kwargs) ... >>> argumente_dict(a="unu", b='doi', c="trei") {'a': 'unu', 'b': 'doi', 'c': 'trei'}
#25. Ce este o funcție lambda?
Funcțiile lambda sunt funcții anonime mici, care pot avea mai multe argumente, dar doar o singură expresie.
>>> aduna = lambda a, b: a + b >>> aduna(1, 3) 4
#26. Care este diferența dintre o funcție normală și o funcție lambda?
Funcțiile normale și lambda sunt similare în funcționalitate. Funcțiile lambda oferă o sintaxă mai concisă pentru exprimarea funcțiilor simple cu o singură expresie, evitând cod suplimentar.
#27. Pentru ce este folosit cuvântul cheie `pass`?
Cuvântul cheie `pass` este folosit pentru a crea un bloc de cod gol, atunci când sintaxa limbajului impune un bloc (de exemplu, în definiția unei funcții, unei clase, unei bucle, etc.), dar încă nu s-a decis codul care va fi implementat.
>>> def aduna(*args): ... ... File "<stdin>", line 3 ^ IndentationError: expected an indented block >>> def aduna(*args): ... pass ... >>>
#28. Ce este o funcție recursivă?
O funcție recursivă este o funcție care se autoapelează direct sau indirect.
Ce sunt operatorii de ambalare (packing) în Python? Cum se utilizează?
Operatorii de ambalare sunt folosiți pentru a colecta mai multe argumente într-o funcție, cunoscuți și ca argumente arbitrare.
Notă: Pentru mai multe detalii, puteți consulta resurse suplimentare despre operatorii de ambalare în Python.
Programarea Orientată pe Obiecte (OOP) în Python
#29. Ce cuvânt cheie este utilizat pentru a crea clase în Python?
Cuvântul cheie `class` este utilizat pentru a crea clase. Este recomandat să se utilizeze convenția de denumire PascalCase pentru clase.
>>> class Masina: ... pass ...
#30. Cum se creează o instanță a unei clase în Python?
O instanță a unei clase se creează apelând clasa ca pe o funcție și specificând argumentele necesare constructorului clasei.
>>> class Masina: ... def __init__(self, culoare): ... self.culoare = culoare ... >>> masina_rosie = Masina('rosie') >>> masina_rosie.culoare 'rosie' >>> masina_verde = Masina('verde') >>> masina_verde.culoare 'verde'
#31. Ce este `self` în Python?
`self` reprezintă instanța curentă a clasei. Acesta este folosit pentru a accesa atributele și metodele obiectului specific din interiorul clasei.
#32. Ce este metoda `__init__`?
`__init__` este metoda constructor a unei clase, similară constructorilor din alte limbaje OOP. Aceasta este apelată automat când se creează o nouă instanță a clasei și este utilizată pentru a inițializa atributele obiectului.
#33. Ce este un docstring în Python?
Un docstring (string de documentare) este un șir de caractere multilinie, utilizat pentru a documenta un bloc de cod, precum o funcție, o clasă sau un modul. De asemenea, poate fi utilizat și ca comentariu multilinie.
Docstringurile sunt accesibile folosind funcția `help()` și sunt esențiale pentru a descrie funcționalitatea metodelor unei clase.
>>> class Masina: ... def __init__(self, culoare): ... self.culoare = culoare ... ... def schimba_culoarea(self, noua_culoare): ... """Această metodă schimbă culoarea mașinii.""" ... self.culoare = noua_culoare ... >>> masina = Masina('rosie') >>> help(masina.schimba_culoarea) Help on method schimba_culoarea in module __main__: schimba_culoarea(noua_culoare) method of __main__.Masina instance Această metodă schimbă culoarea mașinii.
#34. Ce sunt metodele dunder sau magice?
Metodele dunder sau magice sunt metode cu două caractere underscore (`_`) la început și la sfârșit, cum ar fi `__str__`, `__len__`, `__setitem__`, `__getitem__`. Acestea sunt folosite pentru a suprascrie comportamentele default ale obiectelor.
>>> class Masina: ... def __str__(self): ... return "Aceasta este o clasă Masina." ... >>> masina = Masina() >>> print(masina) Aceasta este o clasă Masina.
Notă: Există multe alte metode magice pe care le poți suprascrie. Este util să explorezi documentația oficială pentru mai multe informații despre aceste metode.
#35. Cum implementezi moștenirea în Python?
Moștenirea se implementează specificând clasa părinte ca argument în definiția clasei copil. Se poate apela constructorul clasei părinte folosind `super()` în constructorul clasei copil.
>>> class Animal: ... def __init__(self, nume): ... self.nume = nume ... ... def afiseaza(self): ... print(self.nume) >>> class Cainele(Animal): ... def __init__(self, nume): ... super().__init__(nume) ... >>> catelul = Cainele('Azorel') >>> catelul.afiseaza() Azorel
#36. Cum accesezi clasa părinte din clasa copil în Python?
Se folosește funcția `super()` pentru a face referire la clasa părinte din clasa copil. Astfel, se pot accesa atributele și metodele clasei părinte.
Diverse
#37. Cum folosești comentariile pe o singură linie și pe mai multe linii în Python?
Comentariile pe o singură linie sunt create folosind semnul `#`. Pentru comentarii multilinie, se utilizează ghilimele triple simple (`”’comentarii”’`) sau ghilimele triple duble (`”””comentarii”””`).
#38. Ce este un obiect în Python?
În Python, totul este un obiect. Tipurile de date, funcțiile și clasele sunt toate obiecte.
#39. Care este diferența dintre `is` și `==`?
Operatorul `==` verifică dacă două obiecte au aceeași valoare, în timp ce operatorul `is` verifică dacă două obiecte se referă la aceeași locație din memorie.
>>> a = [] >>> b = [] >>> c = a >>> a == b True >>> a is b False >>> a is c True
#40. Ce sunt copiile superficiale și profunde?
**Copie superficială**: Crează o copie a obiectului original, dar referințele la obiectele conținute rămân aceleași. Astfel, modificările făcute obiectelor din copia superficială vor afecta obiectele din original.
Pentru o copie superficială, se folosește metoda `copy` din modulul `copy`.
>>> from copy import copy >>> a = [1, [2, 3]] >>> b = copy(a) >>> a[1].append(4) >>> a [1, [2, 3, 4]] >>> b [1, [2, 3, 4]]
**Copie profundă**: Creează o copie complet nouă a obiectului, incluzând toate obiectele conținute. Astfel, modificările din copie nu vor afecta obiectul original.
Pentru o copie profundă, se folosește metoda `deepcopy` din modulul `copy`.
>>> from copy import deepcopy >>> a = [1, [2, 3]] >>> b = deepcopy(a) >>> a[1].append(4) >>> a [1, [2, 3, 4]] >>> b [1, [2, 3]] >>> b[1].append(5) >>> a [1, [2, 3, 4]] >>> b [1, [2, 3, 5]]
#41. Ce sunt iteratorii?
Iteratorii sunt obiecte care memorează starea iterației. Ei sunt inițializați cu metoda `__iter__` și returnează următorul element folosind metoda `__next__`.
Pentru a obține următorul element de la un iterator, se folosește funcția `next()`. Obiectele iterabile pot fi transformate în iteratori cu funcția încorporată `iter()`.
>>&