18、通过使用 from 直接加载 mymod 模块的导出项,先按名称加载,然后使用 from * 变体来获取所有内容,以交互方式测试 mymod 模块。
示例代码展示了使用 from * 的情况,如 from mymod import * 后调用 countChars("mymod.py") 。若按名称加载,可将 * 替换为具体要加载的函数名,如 from mymod import countChars ,之后就可以直接调用 countChars 函数进行测试。
19、现在,在一个名为 mymod 的 Python 模块中添加一行代码,使得只有当该模块作为脚本运行时才自动调用 test 函数。尝试从系统命令行运行你的模块;然后导入该模块并交互式地测试其函数。它在这两种模式下是否仍然有效?
为了实现只有当模块作为脚本运行时才自动调用 test 函数,可以在 mymod 模块中添加以下代码:
if __name__ == '__main__':
test()
解释:
-
__name__是 Python 中的一个内置变量。当一个 Python 文件作为脚本直接运行时,__name__的值会被设置为'__main__'。当该文件作为模块被导入时,__name__的值会是模块的名称。 - 因此,
if __name__ == '__main__':这个条件判断可以确保test()函数只在模块作为脚本运行时被调用。
测试步骤:
- 从系统命令行运行模块 :在命令行中输入
python mymod.py,此时test()函数会被自动调用。 - 导入模块并交互式测试 :在 Python 解释器中输入
import mymod,此时test()函数不会被自动调用。你可以手动调用mymod.test()来测试函数。
结论:
通过这种方式, mymod 模块在作为脚本运行和作为模块导入时都能正常工作。作为脚本运行时, test() 函数会自动调用;作为模块导入时,需要手动调用 test() 函数。
20、在递归导入的场景中,导入recur1会引发错误,但如果重启Python并交互式地导入recur2,错误不会出现。请自己测试并观察,然后分析为什么导入recur2可以,而导入recur1不行。(提示:Python在运行新模块的代码之前会将其存储在内置的sys.modules表(一个字典)中;后续的导入会首先从这个表中获取模块,无论该模块是否“完整”。)现在尝试将recur1作为脚本运行:python recur1.py。你会得到与交互式导入recur1时相同的错误吗?为什么?(提示:当模块作为程序运行时,它们不会被导入,这种情况与交互式导入recur2有相同的效果;recur2是第一个被导入的模块。)当你将recur2作为脚本运行时会发生什么?
为什么导入recur2可以,而导入recur1不行
当交互式导入 recur1 时, recur1 会执行其代码。它首先给 X 赋值,然后导入 recur2 。当 recur2 执行 from recur1 import Y 时,由于 recur1 中 Y 还未被赋值,所以会引发 ImportError: cannot import name Y 错误。
而当交互式导入 recur2 时, recur2 首先执行 from recur1 import X ,此时 recur1 中的 X 已经被赋值,所以可以正常导入。接着,由于Python会将模块存储在 sys.modules 表中,后续的导入会首先从这个表中获取模块,即使模块不完整。所以当执行 from recur1 import Y 时,虽然 recur1 中的 Y 还未被赋值,但由于 recur1 已经在 sys.modules 表中,不会再次完整执行 recur1 的代码,避免了无限循环,只是 Y 的值还未被设置,不过不会引发错误。
将recur1作为脚本运行
当将 recur1 作为脚本运行时,它不会被导入,而是直接执行。这就相当于交互式导入 recur2 的情况,因

最低0.47元/天 解锁文章

1055

被折叠的 条评论
为什么被折叠?



