我有一个文件utils.py
,其中包含一个名为f1()
的函数。
我可以从另一个Python脚本import utils
或execfile('utils.py')
访问f1()
。这两种方法有什么区别?
答案 0 :(得分:4)
存在许多差异,但从您的角度来看,最重要的可能是import
可以让您更好地控制utils.py
中定义的对象所在的命名空间。
让我们考虑import
上的三个变体。第一个是你问的问题:
import utils
utils.f1()
utils
是已添加到工作区的唯一符号 - 基础工作区中任何预先存在的f1
都不会被覆盖,如果没有,则{{1}本身不会被承认。对于我打算维护的代码,我更喜欢这种导入方式,因为它使我可以轻松地搜索我的源文件以查找它依赖于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
与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
子句中。