我有一个文件utils.py
,其中包含一个名为f1()
.
从另一个 Python 脚本,我可以import utils
或execfile('utils.py')
有权访问f1()
. 这两种方法有什么区别?
我有一个文件utils.py
,其中包含一个名为f1()
.
从另一个 Python 脚本,我可以import utils
或execfile('utils.py')
有权访问f1()
. 这两种方法有什么区别?
有很多不同之处,但从您的角度来看,最重要的可能是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 *
utils
execfile
__all__
__all__
from utils import *
除了命名空间之外,和之间还有很多区别execfile('utils.py')
。一个是缓存:第二次import
调用utils
将非常快(代码不会重新运行),但第二次调用execfile('utils.py')
可能与第一次调用一样长,因为代码将重新运行。另外,里面可能有一些代码(通常是测试代码)utils.py
作者utils
不想在导入时运行,而只有在文件通过execfile
. 这样的代码放在一个if __name__ == '__main__':
子句中。