理解Python中的__name__==’__main__’

在这个指南中,您将了解到在Python中的if __name__ == ‘__main__’的功能和重要性。

您是否曾经浏览过一个包含不同模块的Python代码库?

如果是的话,您可能会在一个或多个模块中遇到if __name__ == ’__main__’的条件语句。在接下来的几分钟里,我们将揭示上述条件语句的含义,并查看一个可以帮助的示例。

让我们开始吧!

__name__在Python中的重要性是什么?

在Python中,一个模块是一个包含函数定义、一组要求评估的表达式等的.py文件。例如,如果我们有一个名为hello_world.py的文件,我们将称之为hello_world.py文件或hello_world模块。

当您运行一个Python模块时,Python interpreter会在执行前为一些特殊变量设置值:其中之一是__name__。理解__name__的重要性的关键在于理解在Python中如何工作。

📁 Download the code for this section here

转到文件夹example-1。我们有文件module1.py。变量__name__在当前模块的命名空间中。

该模块打印出一行,然后是__name__变量的值。

# example-1/module1.py
print("这是模块1。")
print(f"模块1的__name__变量是:{__name__}。")

现在,让我们从命令行运行module1

$ python module1.py

在输出中,我们可以看到__name__变量被设置为__main__。

这是模块1。
模块1的__name__变量是:__main__。

在Python中导入模块

除了运行一个Python模块,有时您可能希望在当前模块中使用另一个Python模块的功能。Python通过导入实现了这一点。

通过导入到当前模块的范围内,导入允许您重用另一个模块的功能,而无需重写代码。

文件module2.py包含以下内容。我们在module2中导入了module1

# example-1/module2.py

import module1 # 导入module1

print(f"这是模块2")
print(f"模块2的__name__变量是:{__name__}。")

我们运行module2.py并观察输出。

$ python module2.py

在下面的输出中:

  • 我们可以看到当我们在module2中导入module1时,module1在幕后运行,并打印出相应的输出。
  • 但是这次,__name__变量不是__main__,而是module1
  • 因为我们直接运行了module2,所以与模块对应的__name__变量现在是__main__。
输出

这是模块1。
模块1的__name__变量是:module1。
这是模块2
模块2的__name__变量是:__main__。

💡 关键思想:

– 如果一个模块被直接运行,它的__name__变量被设置为__main__。

– 如果一个模块在另一个模块内被导入,它的__name__被设置为模块的名称。

Python中if __name__==’__main__’的示例

在本节中,我们将看到if __name__ == ‘__main__’条件的一个实际用例。我们将定义一个简单的函数,然后编写单元测试来检查函数是否按预期工作。

📁 Download the code and follow along.

该部分的代码可以在example-2文件夹中找到。

在这里,add.py是一个包含add_ab()函数定义的link_4

# example-2/add.py

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

我们将使用Python的unittest模块来测试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)
    

上面的代码执行以下操作:

  • 导入Python的内置的unittest模块
  • add模块导入add_ab()函数
  • 定义了一个测试类TestAdd,并在该测试类内部作为方法定义了一组测试用例

要为代码设置单元测试,首先应该定义一个从unittest.TestCase继承的测试类。所有的测试用例都应该作为类内部的方法来指定,并且应该以test_开头。

注意:如果您不将方法命名为test_,您会发现相应的测试用例不会被检测到,因此不会运行。

现在让我们尝试从终端运行test_add模块。

$ python test_add.py

您将看到没有输出,也没有运行任何测试。

为什么会这样呢?🤔

这是因为要运行单元测试,您应该在运行test_add.py时,将unittest作为主模块运行,使用以下命令。

$ python -m unittest test_add.py

运行上述冗长的命令后,我们可以看到所有三个测试都已成功运行。

输出
...
----------------------------------------------------------------------
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)

# 将unittest作为主模块运行
if __name__ == '__main__':
        unittest.main()

上述代码片段中的条件告诉Python解释器:如果直接运行此模块,则运行unittest.main()内部的代码。

在添加了上述两行代码后,您可以运行test_add模块。

$ python test_add.py

▶️ 现在直接运行测试添加模块将会运行我们定义的所有三个测试。

输出
...
----------------------------------------------------------------------
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。

输出
.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被定义为测试类中的第三个方法,但相应的测试是第二个运行的。

总结

我希望本教程帮助您理解Python中的if __name__ == ‘__main__'条件语句的工作原理。

以下是关键要点的快速回顾:

  • Python解释器在执行Python脚本之前设置__name__变量。
  • 当直接运行一个模块时,__name__的值是__main__
  • 当在另一个Python脚本中导入一个模块时,__name__的值是模块名。
  • 您可以使用if __name__ == '__main__'来控制执行以及模块在直接运行和导入运行时的哪些部分运行。

接下来,查看这篇关于Python sets的深入指南。愉快学习!🎉

类似文章