Κατανόηση εάν __name__ == ‘__main__’ στην Python

Σε αυτόν τον οδηγό, θα κατανοήσετε τη λειτουργικότητα και τη σημασία του if __name__ == ‘__main__’ στην Python.

Έχετε περάσει ποτέ από μια βάση κώδικα Python με διαφορετικές ενότητες;

Εάν ναι, πιθανότατα θα συναντούσατε εάν __name__ == ‘__main__’ υπό όρους σε μία ή περισσότερες ενότητες. Μέσα στα επόμενα λεπτά, θα απομυθοποιήσουμε τι σημαίνει η παραπάνω υπό όρους και θα δούμε ένα παράδειγμα όπου μπορεί να είναι χρήσιμο.

Ας ξεκινήσουμε!

Ποια είναι η σημασία του __name__ στην Python;

Στην Python, μια λειτουργική μονάδα είναι ένα αρχείο .py που περιέχει ορισμούς συναρτήσεων, ένα σύνολο παραστάσεων προς αξιολόγηση και πολλά άλλα. Για παράδειγμα, εάν έχουμε ένα αρχείο με το όνομα hello_world.py, αναφερόμαστε σε αυτό ως αρχείο hello_world.py ή ως λειτουργική μονάδα hello_world.

Όταν εκτελείτε μια λειτουργική μονάδα Python, ο διερμηνέας Python ορίζει τις τιμές για μερικές ειδικές μεταβλητές πριν από την εκτέλεση: η __name__ είναι μία από αυτές. Το κλειδί για την κατανόηση της σημασίας __name__ είναι η κατανόηση του τρόπου λειτουργίας των εισαγωγών στην Python.

📁 Κατεβάστε τον κωδικό για αυτήν την ενότητα εδώ.

Μεταβείτε στο φάκελο παράδειγμα-1. Έχουμε το αρχείο module1.py. Η μεταβλητή __name__ βρίσκεται στον χώρο ονομάτων της τρέχουσας λειτουργικής μονάδας.

Αυτή η ενότητα εκτυπώνει μια γραμμή ακολουθούμενη από την τιμή της μεταβλητής __name__.

# example-1/module1.py
print("This is module1.")
print(f"The __name__ variable of module 1 is: {__name__}.")

Τώρα, ας τρέξουμε το module1 από τη γραμμή εντολών.

$ python module1.py

Στην έξοδο, βλέπουμε ότι η μεταβλητή __name__ έχει οριστεί σε __main__.

This is module1.
The __name__ variable of module 1 is: __main__.

Εισαγωγή μονάδων σε Python

Εκτός από την εκτέλεση μιας λειτουργικής μονάδας Python, μερικές φορές μπορεί να θέλετε να χρησιμοποιήσετε τη λειτουργικότητα από μια άλλη λειτουργική μονάδα Python μέσα στην τρέχουσα λειτουργική μονάδα. Η Python το διευκολύνει μέσω εισαγωγών.

  Τι είναι το Kodi; Όλα όσα ΠΡΕΠΕΙ να γνωρίζετε για την εφαρμογή τηλεοπτικής ροής

Οι εισαγωγές σάς επιτρέπουν να χρησιμοποιήσετε ξανά τη λειτουργικότητα μιας άλλης λειτουργικής μονάδας—με την εισαγωγή της στο πεδίο εφαρμογής της τρέχουσας λειτουργικής μονάδας—χωρίς να χρειάζεται να ξαναγράψετε τον κώδικα.

Το αρχείο module2.py περιέχει τα ακόλουθα. Έχουμε εισαγάγει το module1 στο εσωτερικό. ενότητα 2.

# example-1/module2.py

import module1 # module1 is imported

print(f"This is module2")
print(f"The __name__ variable of module2 is: {__name__}.")

Εκτελούμε το module2.py και παρατηρούμε την έξοδο.

$ python module2.py

Στην παρακάτω έξοδο:

  • Βλέπουμε ότι το module1 εκτελείται κάτω από την κουκούλα όταν το εισάγουμε μέσα στο module2 και εκτυπώνεται η αντίστοιχη έξοδος.
  • Αλλά αυτή τη φορά, η μεταβλητή __name__ δεν είναι __main__ αλλά ενότητα1.
  • Επειδή τρέξαμε απευθείας το module2, η μεταβλητή __name__ που αντιστοιχεί στη λειτουργική μονάδα είναι τώρα __main__.
Output

This is module1.
The __name__ variable of module 1 is: module1.
This is module2
The __name__ variable of module2 is: __main__.

💡 Βασική ιδέα:

– Εάν μια λειτουργική μονάδα εκτελείται απευθείας, η μεταβλητή __name__ της είναι ίση με __main__.

– Εάν μια λειτουργική μονάδα εισάγεται μέσα σε άλλη λειτουργική μονάδα, το __name__ της ορίζεται στο όνομα της λειτουργικής μονάδας.

Παράδειγμα του if __name__==’__main__’ στην Python

Στην ενότητα, θα δούμε μια πρακτική περίπτωση χρήσης του if __name__ == ‘__main__’ υπό όρους. Θα ορίσουμε μια απλή συνάρτηση και στη συνέχεια θα γράψουμε δοκιμές μονάδας για να ελέγξουμε αν η λειτουργία λειτουργεί όπως αναμένεται.

📁 Κατεβάστε τον κώδικα και ακολουθήστε τον.

Ο κώδικας αυτής της ενότητας βρίσκεται στο φάκελο example-2.

Εδώ, το add.py είναι ένα αρχείο Python που περιέχει τον ορισμό της συνάρτησης add_ab(). Η συνάρτηση add_ab() παίρνει οποιουσδήποτε δύο αριθμούς και επιστρέφει το άθροισμά τους.

# example-2/add.py

def add_ab(a,b):
    return a + b

Θα χρησιμοποιήσουμε το unittest module της Python για να δοκιμάσουμε τη συνάρτηση add_ab().

  Γιατί δεν εμφανίζεται το πληκτρολόγιο οθόνης στο iPad μου;

Γράψιμο δοκιμών για μια συνάρτηση Python

Κοιτάξτε το απόσπασμα κώδικα παρακάτω, που περιέχει τα περιεχόμενα της ενότητας test_add.

# example-2/test_add.py

import unittest
from add import add_ab

class TestAdd(unittest.TestCase):
    def test_add_23(self):
        self.assertEqual(add_ab(2,3), 5)
    
    def test_add_19(self):
        self.assertEqual(add_ab(1,9), 10)
    
    def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), -6)
    

Ο παραπάνω κώδικας κάνει τα εξής:

  • Εισάγει την ενσωματωμένη ενότητα δοκιμής της Python
  • Εισάγει τη συνάρτηση add_ab() από τη μονάδα προσθήκης
  • Καθορίζει την κλάση δοκιμής TestAdd και ένα σύνολο δοκιμαστικών περιπτώσεων ως μεθόδους εντός της κλάσης δοκιμής

Για να ρυθμίσετε δοκιμές μονάδας για τον κώδικά σας, θα πρέπει πρώτα να ορίσετε μια κλάση δοκιμής που κληρονομείται από το unittest.TestCase. Όλες οι περιπτώσεις δοκιμών θα πρέπει να προσδιορίζονται ως μέθοδοι εντός της τάξης και θα πρέπει να ξεκινούν με το test_.

Σημείωση: Εάν δεν ονομάσετε τις μεθόδους ως test_, θα δείτε ότι οι αντίστοιχες δοκιμές δεν θα εντοπιστούν και επομένως δεν θα εκτελεστούν.

Τώρα ας δοκιμάσουμε να εκτελέσουμε την ενότητα test_add από το τερματικό.

$ python test_add.py

Θα δείτε ότι δεν υπάρχει έξοδος και κανένα από τα τεστ δεν έχει εκτελεστεί.

Γιατί συμβαίνει αυτό;🤔

Αυτό συμβαίνει επειδή για να εκτελέσετε τις δοκιμές μονάδας, θα πρέπει να εκτελέσετε το unittest ως κύρια λειτουργική μονάδα ενώ εκτελείτε το test_add.py, χρησιμοποιώντας την παρακάτω εντολή.

$ python -m unittest test_add.py

Με την εκτέλεση της παραπάνω αναλυτικής εντολής, βλέπουμε ότι και οι τρεις δοκιμές έχουν εκτελεστεί με επιτυχία.

Output
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

Ωστόσο, θα είναι βολικό να εκτελούνται οι δοκιμές όταν εκτελείται αυτή η ενότητα test_add, ναι; Ας μάθουμε πώς να το κάνουμε στην επόμενη ενότητα.

Χρησιμοποιώντας το if __name__ == ‘__main__’ για να εκτελέσετε τη δοκιμή μονάδας ως κύρια μονάδα

Εάν θέλετε να εκτελέσετε όλες τις δοκιμές μονάδας όταν η λειτουργική μονάδα εκτελείται απευθείας, μπορείτε να προσθέσετε την υπό όρους.

# example-2/test_add.py

import unittest
from add import add_ab

class TestAdd(unittest.TestCase):
    def test_add_23(self):
        self.assertEqual(add_ab(2,3), 5)
    
    def test_add_19(self):
        self.assertEqual(add_ab(1,9), 10)
    
    def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), -6)

# Run unittest as the main module
if __name__ == '__main__':
        unittest.main()

Η υπό όρους στο παραπάνω απόσπασμα κώδικα λέει στον διερμηνέα της Python: Εάν αυτή η λειτουργική μονάδα εκτελείται απευθείας, τότε εκτελέστε τον κώδικα μέσα. unittest.main().

  Αξίζει να ξοδέψετε επιπλέον 200 £;

Μπορείτε να εκτελέσετε την ενότητα test_add αφού προσθέσετε τις παραπάνω δύο γραμμές κώδικα.

$ python test_add.py

▶️ Με την απευθείας εκτέλεση της ενότητας δοκιμαστικής προσθήκης εκτελούνται τώρα και οι τρεις δοκιμές που έχουμε ορίσει.

Output
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

Η παραπάνω έξοδος ΟΚ υποδεικνύει ότι όλες οι δοκιμές εκτελέστηκαν με επιτυχία. Οι τρεις τελείες… υποδεικνύουν ότι έγιναν τρεις δοκιμές και όλες πέρασαν.

Τώρα, ας αλλάξουμε την αναμενόμενη τιμή επιστροφής test_add_1_minus7 σε 8. Επειδή η συνάρτηση επιστρέφει – 6 σε αυτήν την περίπτωση, θα πρέπει να υπάρχει μία δοκιμή αποτυχίας.

def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), 8)

Όπως φαίνεται στην παρακάτω έξοδο, παίρνουμε .F., από τις τρεις δοκιμές, το μοτίβο ενός από αυτά απέτυχε (η δεύτερη δοκιμή) και στο traceback, λαμβάνουμε ένα AssertionError που δηλώνει – 6 != 8.

Output
.F.
======================================================================
FAIL: test_add_1_minus7 (__main__.TestAdd)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_add.py", line 12, in test_add_1_minus7
    self.assertEqual(add_ab(1,-7), 8)
AssertionError: -6 != 8

----------------------------------------------------------------------
Ran 3 tests in 0.021s

FAILED (failures=1)

Ένα σημαντικό πράγμα που πρέπει να σημειωθεί είναι ότι οι δοκιμές δεν εκτελούνται απαραίτητα με την ίδια σειρά με την οποία καθορίζονται στην κατηγορία δοκιμής. Στο παραπάνω παράδειγμα, η test_add_1_minus7 ορίζεται ως η τρίτη μέθοδος στην κλάση δοκιμής, αλλά η αντίστοιχη δοκιμή εκτελέστηκε δεύτερη.

Ανακεφαλαίωση

Ελπίζω αυτό το σεμινάριο να σας βοήθησε να κατανοήσετε πώς λειτουργεί η συνθήκη if __name__ == ‘__main__’ στην Python.

Ακολουθεί μια γρήγορη ανακεφαλαίωση των βασικών γεγονότων:

  • Ο διερμηνέας Python θέτει τη μεταβλητή __name__ πριν από την εκτέλεση του σεναρίου Python.
  • Όταν εκτελείτε απευθείας μια λειτουργική μονάδα, η τιμή του __name__ είναι __main__.
  • Όταν εισάγετε μια λειτουργική μονάδα μέσα σε άλλο σενάριο Python, η τιμή του __name__ είναι το όνομα της μονάδας.
  • Μπορείτε να χρησιμοποιήσετε το if __name__ == ‘__main__’ για να ελέγξετε την εκτέλεση και ποια τμήματα της λειτουργικής μονάδας εκτελούνται κατά τη διάρκεια άμεσων και εισαγόμενων εκτελέσεων, αντίστοιχα.

Στη συνέχεια, ελέγξτε αυτόν τον αναλυτικό οδηγό για σύνολα Python. Καλή μάθηση!🎉