理解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中如何工作。
转到文件夹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__’条件的一个实际用例。我们将定义一个简单的函数,然后编写单元测试来检查函数是否按预期工作。
该部分的代码可以在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的深入指南。愉快学习!🎉