7

我有一个文件utils.py,其中包含一个名为f1().

从另一个 Python 脚本,我可以import utilsexecfile('utils.py')有权访问f1(). 这两种方法有什么区别?

4

1 回答 1

6

有很多不同之处,但从您的角度来看,最重要的可能是import让您可以更好地控制utils.py最终定义的对象所在的命名空间。

让我们考虑import. 第一个是你问的那个:

import utils
utils.f1()

utils是唯一添加到您的工作区的符号 - 基本工作区中的任何预先存在的符号f1都不会被覆盖,如果没有,则f1()不会单独识别。对于我打算维护的代码,我非常喜欢这种导入方式,因为它使我可以轻松地在源文件中搜索它所依赖的所有位置utils

但是,如果utils.f1()每次都说得太冗长,那么您可以这样做:

from utils import f1
f1()

现在,如果您说f1()将调用utils.f1(),因为这是您现在与f1工作区中的名称相关联的代码对象。现在要大致了解您的代码在哪里依赖于utils模块变得稍微困难​​了。但至少这种类型的import语句可以让您精确控制导入哪些符号,哪些不导入。您甚至可以在此过程中重命名符号:

from utils import f1 as EffOne
EffOne()  

最后,您可以选择完全失去对命名空间的控制:

from utils import *

现在,谁知道导入了哪些符号:基本上是所有utils必须提供给世界的东西(或者,如果utils开发人员不厌其烦地指定一个__all__属性,那么这里列出的所有东西)。如果有的话,我建议您import *仅将其用于快速而肮脏的编程。

execfile从命名空间的角度来看,这实际上是最接近的导入样式:其作用与将所有由willy-nilly定义的符号转储到您的工作区execfile('utils.py')中的作用大致相同。一个细微的区别是,如果已定义,它甚至不会将其限制在符号中- 事实上,符号本身只会与其他所有东西一起被扔在你的腿上。from utils import *utilsexecfile__all____all__

from utils import *除了命名空间之外,和之间还有很多区别execfile('utils.py')。一个是缓存:第二次import调用utils将非常快(代码不会重新运行),但第二次调用execfile('utils.py')可能与第一次调用一样长,因为代码重新运行。另外,里面可能有一些代码(通常是测试代码)utils.py作者utils不想在导入时运行,而只有在文件通过execfile. 这样的代码放在一个if __name__ == '__main__':子句中。

于 2014-12-17T01:43:41.993 回答