ทำความเข้าใจว่า __name__ == ‘__main__’ ใน Python

ในคู่มือนี้ คุณจะเข้าใจการทำงานและความสำคัญของ if __name__ == ‘__main__’ ใน Python

คุณเคยอ่านผ่าน Python codebase ด้วยโมดูลต่างๆ หรือไม่?

ถ้าใช่ คุณอาจเคยเจอเงื่อนไข __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 อำนวยความสะดวกนี้ผ่านการนำเข้า

การนำเข้าทำให้คุณสามารถใช้ฟังก์ชันของโมดูลอื่นซ้ำได้ โดยการนำเข้าไปยังขอบเขตของโมดูลปัจจุบัน โดยไม่ต้องเขียนโค้ดใหม่

  วิธีเปิดใช้งานกล้องใน Omegle

ไฟล์ 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

ในผลลัพธ์ด้านล่าง:

  • เราเห็นว่าโมดูล 1 ทำงานภายใต้ประทุนเมื่อเรานำเข้าภายในโมดูล 2 และเอาต์พุตที่เกี่ยวข้องจะถูกพิมพ์ออกมา
  • แต่คราวนี้ ตัวแปร __name__ ไม่ใช่ __main__ แต่เป็น module1
  • เนื่องจากเรารัน 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__’ conditional เราจะกำหนดฟังก์ชันอย่างง่าย จากนั้นจึงเขียนการทดสอบหน่วยเพื่อตรวจสอบว่าฟังก์ชันทำงานตามที่คาดไว้หรือไม่

📁 ดาวน์โหลดรหัสและปฏิบัติตาม

รหัสสำหรับส่วนนี้สามารถพบได้ในโฟลเดอร์ตัวอย่าง-2

ที่นี่ add.py เป็นไฟล์ Python ที่มีคำจำกัดความของฟังก์ชัน add_ab().ฟังก์ชัน add_ab() ใช้ตัวเลขสองตัวใดๆ และส่งคืนผลรวม

# example-2/add.py

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

เราจะใช้โมดูล unittest ของ Python เพื่อทดสอบฟังก์ชัน add_ab()

การเขียนกรณีทดสอบสำหรับฟังก์ชัน 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)
    

รหัสด้านบนทำสิ่งต่อไปนี้:

  • นำเข้าโมดูล unittest ในตัวของ Python
  • นำเข้าฟังก์ชัน add_ab() จากโมดูลเพิ่ม
  • กำหนดคลาสการทดสอบ TestAdd และชุดของกรณีทดสอบเป็นเมธอดภายในคลาสการทดสอบ
  Thunderbolt 3 กับ USB-C: อะไรคือความแตกต่าง?

ในการตั้งค่าการทดสอบหน่วยสำหรับโค้ดของคุณ ก่อนอื่นคุณควรกำหนดคลาสการทดสอบที่สืบทอดจาก unittest.TestCase กรณีทดสอบทั้งหมดควรระบุเป็นเมธอดภายในคลาส และควรเริ่มต้นด้วย test_

หมายเหตุ: หากคุณไม่ตั้งชื่อเมธอดเป็น test_ คุณจะเห็นว่าการทดสอบที่เกี่ยวข้องจะไม่ถูกตรวจพบ ดังนั้น จะไม่ทำงาน

ตอนนี้ ให้ลองเรียกใช้โมดูล test_add จากเทอร์มินัล

$ python test_add.py

คุณจะเห็นว่าไม่มีเอาต์พุต และไม่มีการทดสอบใดทำงาน

ทำไมถึงเป็นอย่างนี้🤔

เนื่องจากในการรัน unittest คุณควรรัน unittest เป็นโมดูลหลักขณะรัน test_add.py โดยใช้คำสั่งด้านล่าง

$ python -m unittest test_add.py

เมื่อรันคำสั่ง verbose ด้านบน เราจะเห็นว่าการทดสอบทั้งสามทำงานสำเร็จแล้ว

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

OK

อย่างไรก็ตาม จะสะดวกที่จะทำการทดสอบเมื่อเรียกใช้โมดูลนี้ test_add ใช่ไหม มาเรียนรู้วิธีการทำในหัวข้อถัดไป

ใช้ if __name__ == ‘__main__’ เพื่อเรียกใช้ unittest เป็นโมดูลหลัก

หากคุณต้องการเรียกใช้การทดสอบหน่วยทั้งหมดเมื่อโมดูลทำงานโดยตรง คุณสามารถเพิ่มเงื่อนไขได้

# 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().

คุณสามารถเรียกใช้โมดูล test_add หลังจากเพิ่มโค้ดสองบรรทัดข้างต้น

$ python test_add.py

▶️ การรันโมดูลเพิ่มการทดสอบโดยตรง ตอนนี้จะรันการทดสอบทั้งสามที่เรากำหนดไว้

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

OK

ผลลัพธ์ข้างต้น OK บ่งชี้ว่าการทดสอบทั้งหมดดำเนินการได้สำเร็จ จุดสามจุด … ระบุว่ามีการทดสอบสามครั้งและผ่านทั้งหมด

ตอนนี้ ให้เราเปลี่ยนค่าส่งคืนที่คาดไว้ test_add_1_minus7 เป็น 8 เนื่องจากฟังก์ชันส่งคืน – 6 ในกรณีนี้ ควรมีการทดสอบที่ล้มเหลวหนึ่งครั้ง

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

ตามที่เห็นในผลลัพธ์ด้านล่าง เราได้รับ .F. จากการทดสอบสามแบบ รูปแบบที่หนึ่งล้มเหลว (การทดสอบครั้งที่สอง) และในการติดตามกลับ เราได้รับ 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 ถูกกำหนดเป็นเมธอดที่สามในคลาสการทดสอบ แต่รันการทดสอบที่สอดคล้องกันเป็นครั้งที่สอง

  รหัสข้อผิดพลาด 36 บน Mac คืออะไร

สรุป

ฉันหวังว่าบทช่วยสอนนี้จะช่วยให้คุณเข้าใจว่าเงื่อนไข if __name__ == ‘__main__’ ทำงานอย่างไรใน Python

ต่อไปนี้คือสรุปประเด็นสำคัญโดยย่อ:

  • ล่าม Python ตั้งค่าตัวแปร __name__ ก่อนดำเนินการสคริปต์ Python
  • เมื่อคุณเรียกใช้โมดูลโดยตรง ค่าของ __name__ คือ __main__
  • เมื่อคุณนำเข้าโมดูลภายในสคริปต์ Python อื่น ค่าของ __name__ จะเป็นชื่อโมดูล
  • คุณสามารถใช้ if __name__ == ‘__main__’ เพื่อควบคุมการดำเนินการและส่วนใดของโมดูลที่ทำงานระหว่างการวิ่งโดยตรงและที่นำเข้าตามลำดับ

ถัดไป ดูคำแนะนำเชิงลึกเกี่ยวกับชุด Python มีความสุขในการเรียนรู้!🎉

เรื่องล่าสุด

x