Înțelegerea funcționalității și semnificației `if __name__ == ‘__main__’` în Python
Te-ai confruntat vreodată cu un cod Python structurat pe mai multe module?
Dacă da, este foarte probabil să fi întâlnit condiția `if __name__ == ‘__main__’` în unul sau mai multe dintre aceste module. În următoarele minute, vom clarifica sensul acestei construcții și vom analiza un scenariu practic unde aceasta devine deosebit de utilă.
Să începem explorarea!
Care este importanța variabilei `__name__` în Python?
În universul Python, un modul este, de fapt, un fișier cu extensia `.py`, care include definiții de funcții, instrucțiuni care trebuie executate și alte elemente de programare. Spre exemplu, dacă avem un fișier numit `exemplu.py`, ne referim la el ca la fișierul `exemplu.py` sau modulul `exemplu`.
În momentul în care un modul Python este executat, interpretorul Python stabilește valorile anumitor variabile speciale înainte de a începe execuția. Una dintre aceste variabile este `__name__`. Cheia pentru a înțelege semnificația lui `__name__` constă în modul în care funcționează importurile în Python.
📁 Descarcă de aici codul pentru această secțiune.
Navighează la folderul `exemplu-1`. Aici vei găsi fișierul `modul1.py`. Variabila `__name__` este localizată în spațiul de nume al modulului curent.
Acest modul tipărește un mesaj și apoi valoarea variabilei `__name__`.
# exemplu-1/modul1.py print("Acesta este modulul 1.") print(f"Valoarea variabilei __name__ în modulul 1 este: {__name__}.")
Acum, să executăm `modul1` direct din linia de comandă.
$ python modul1.py
În rezultatul obținut, observăm că variabila `__name__` este setată la `__main__`.
Acesta este modulul 1. Valoarea variabilei __name__ în modulul 1 este: __main__.
Cum importăm module în Python?
Pe lângă rularea directă a unui modul, uneori vei dori să folosești funcționalitățile altor module Python în interiorul modulului curent. Python face acest lucru posibil prin importuri.
Importurile îți permit să refolosești codul din alt modul, aducându-l în spațiul de lucru al modulului curent, fără a fi nevoie să rescrii același cod.
Fișierul `modul2.py` conține următorul cod. Aici am importat `modul1` în `modul2`.
# exemplu-1/modul2.py import modul1 # modul1 este importat print(f"Acesta este modulul 2") print(f"Valoarea variabilei __name__ în modulul 2 este: {__name__}.")
Executăm `modul2.py` și examinăm rezultatul.
$ python modul2.py
În rezultatul de mai jos:
- Observăm că `modul1` este executat atunci când este importat în `modul2`, iar rezultatul său este afișat.
- De această dată, valoarea variabilei `__name__` nu este `__main__`, ci `modul1`.
- Deoarece `modul2` a fost executat direct, valoarea variabilei `__name__` corespunzătoare modulului este acum `__main__`.
Ieșire Acesta este modulul 1. Valoarea variabilei __name__ în modulul 1 este: modul1. Acesta este modulul 2 Valoarea variabilei __name__ în modulul 2 este: __main__.
💡 Punct cheie:
– Dacă un modul este executat direct, valoarea variabilei sale `__name__` devine `__main__`.
– Dacă un modul este importat într-un alt modul, valoarea `__name__` este setată la numele modulului.
Exemplu de utilizare `if __name__ == ‘__main__’` în Python
În această secțiune, vom explora un caz practic de folosire a condiției `if __name__ == ‘__main__’`. Vom defini o funcție simplă și vom crea teste unitare pentru a verifica funcționalitatea acesteia.
📁 Descarcă codul și urmărește pașii.
Codul pentru această secțiune se găsește în folderul `exemplu-2`.
Aici, fișierul `adunare.py` conține definiția funcției `aduna_ab()`. Funcția `aduna_ab()` primește două numere și returnează suma acestora.
# exemplu-2/adunare.py def aduna_ab(a, b): return a + b
Vom utiliza modulul `unittest` din Python pentru a testa funcția `aduna_ab()`.
Cum scriem cazuri de test pentru o funcție Python?
Analizează codul de mai jos, care reprezintă conținutul modulului `test_adunare`.
# exemplu-2/test_adunare.py import unittest from adunare import aduna_ab class TestAdunare(unittest.TestCase): def test_aduna_23(self): self.assertEqual(aduna_ab(2, 3), 5) def test_aduna_19(self): self.assertEqual(aduna_ab(1, 9), 10) def test_aduna_1_minus7(self): self.assertEqual(aduna_ab(1, -7), -6)
Codul de mai sus face următoarele acțiuni:
- Importă modulul `unittest` încorporat în Python.
- Importă funcția `aduna_ab()` din modulul `adunare`.
- Definește clasa de test `TestAdunare` și o serie de cazuri de testare ca metode în interiorul clasei de test.
Pentru a configura teste unitare pentru codul tău, trebuie mai întâi să definești o clasă de test care moștenește din `unittest.TestCase`. Toate cazurile de testare trebuie definite ca metode în interiorul clasei și trebuie să înceapă cu `test_`.
Notă: Dacă nu denumești metodele ca `test_
Acum, să încercăm să executăm modulul `test_adunare` direct din terminal.
$ python test_adunare.py
Vom observa că nu apare niciun rezultat și niciun test nu a fost executat.
De ce se întâmplă acest lucru? 🤔
Aceasta se întâmplă deoarece, pentru a executa testele unitare, trebuie să rulezi `unittest` ca modul principal atunci când rulezi `test_adunare.py`, folosind comanda de mai jos.
$ python -m unittest test_adunare.py
După execuția comenzii detaliate mai sus, observăm că toate cele trei teste au rulat cu succes.
Ieșire ... ---------------------------------------------------------------------- Am executat 3 teste în 0.000s OK
Cu toate acestea, nu ar fi mai convenabil să rulezi testele atunci când modulul `test_adunare` este executat direct? Hai să vedem cum putem face asta în secțiunea următoare.
Utilizarea `if __name__ == ‘__main__’` pentru a rula `unittest` ca modul principal
Dacă vrei să rulezi toate testele unitare când modulul este executat direct, poți adăuga condiția.
# exemplu-2/test_adunare.py import unittest from adunare import aduna_ab class TestAdunare(unittest.TestCase): def test_aduna_23(self): self.assertEqual(aduna_ab(2, 3), 5) def test_aduna_19(self): self.assertEqual(aduna_ab(1, 9), 10) def test_aduna_1_minus7(self): self.assertEqual(aduna_ab(1, -7), -6) # Rulează unittest ca modul principal if __name__ == '__main__': unittest.main()
Condiția din codul de mai sus îi spune interpretorului Python: Dacă acest modul este executat direct, atunci rulează codul din interior, adică `unittest.main()`.
Poți executa modulul `test_adunare` după adăugarea celor două linii de cod de mai sus.
$ python test_adunare.py
▶️ Acum, executarea directă a modulului de testare a adunării va rula toate cele trei teste definite.
Ieșire ... ---------------------------------------------------------------------- Am executat 3 teste în 0.000s OK
Rezultatul de mai sus, `OK`, indică faptul că toate testele au fost executate cu succes. Cele trei puncte `…` indică faptul că trei teste au fost efectuate și toate au trecut.
Acum, să modificăm valoarea de returnare așteptată a testului `test_aduna_1_minus7` la 8. Deoarece funcția returnează -6 în acest caz, ar trebui să avem un test eșuat.
def test_aduna_1_minus7(self): self.assertEqual(aduna_ab(1, -7), 8)
După cum vedem în rezultatul de mai jos, obținem `.F.`, dintre cele trei teste, unul dintre ele a eșuat (al doilea test), iar în informațiile despre eroare, obținem o `AssertionError` care indică faptul că -6 nu este egal cu 8.
Ieșire .F. ====================================================================== EȘEC: test_aduna_1_minus7 (__main__.TestAdunare) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_adunare.py", line 12, in test_aduna_1_minus7 self.assertEqual(aduna_ab(1, -7), 8) AssertionError: -6 != 8 ---------------------------------------------------------------------- Am executat 3 teste în 0.021s EȘEC (eșecuri=1)
Un aspect important de reținut este că testele nu sunt neapărat executate în aceeași ordine în care au fost definite în clasa de test. În exemplul de mai sus, `test_aduna_1_minus7` este definită ca a treia metodă din clasa de testare, dar testul corespunzător a fost executat al doilea.
Rezumat
Sperăm că acest ghid te-a ajutat să înțelegi mai bine cum funcționează condiția `if __name__ == ‘__main__’` în Python.
Iată o recapitulare a principalelor concluzii:
- Interpretorul Python stabilește valoarea variabilei `__name__` înainte de a executa un script Python.
- Când execuți un modul direct, valoarea `__name__` este `__main__`.
- Când imporți un modul într-un alt script Python, valoarea `__name__` este numele modulului.
- Poți folosi `if __name__ == ‘__main__’` pentru a controla execuția și ce părți ale modulului rulează în timpul execuțiilor directe și în timpul importurilor.
În continuare, te invităm să consulți acest ghid detaliat despre seturile în Python. Învățare plăcută! 🎉