问题描述
我有一个文件utils.py
,其中包含一个名为f1()
的函数.
I have a file utils.py
containing a function called f1()
.
从另一个Python脚本中,我可以import utils
或execfile('utils.py')
并可以访问f1()
.两种方法有什么区别?
From another Python script I can import utils
or execfile('utils.py')
and have access to f1()
. What are the differences between the two methods?
推荐答案
有很多区别,但是从您的角度来看,最重要的是import
可以让您更好地控制在其中定义对象的名称空间utils.py
结束.
There are many differences, but from your point of view the most significant is probably that import
gives you more control over the namespace in which the objects defined in utils.py
end up.
让我们考虑import
上的三个变体.第一个是您问过的:
Let's consider three variants on import
. The first is the one you asked about:
import utils
utils.f1()
utils
是唯一添加到您的工作空间中的符号-基本工作空间中任何先前存在的f1
都不会被覆盖,并且如果没有,则f1()
本身不会被覆盖被认可.对于我打算维护的代码,我非常喜欢这种导入方式,因为它使我可以轻松地在源文件中搜索依赖于utils
的所有位置.
utils
is the only symbol that has been added to your workspace—any pre-existing f1
in your base workspace will not have been overwritten, and if there is none, then f1()
on its own will not be recognized. For code I intend to maintain, I greatly prefer this way of importing, because it makes it easy for me to search my source file for all the places in which it depends on utils
.
但是如果每次都说utils.f1()
太冗长,那么您可以这样做:
But if saying utils.f1()
every time is too verbose then you can do this:
from utils import f1
f1()
现在,如果您说将调用utils.f1()
的f1()
,因为这是您现在与工作空间中的名称f1
关联的代码对象.现在,要稍微了解一下您的代码在utils
模块上所处的位置,就比较困难.但是,至少这种类型的import
语句可让您精确控制导入的符号和不导入的符号.您甚至可以在此过程中重命名符号:
Now if you say f1()
that will call utils.f1()
, because that is the code object that you have now associated with the name f1
in your workspace. It's now slightly harder to get an overview of where your code is reliant on the utils
module. But at least this type of import
statement gives you precise control over which symbols were imported and which not. You can even rename symbols during this process:
from utils import f1 as EffOne
EffOne()
最后,您可以选择完全失去对名称空间的控制:
Finally you can choose to lose control over the namespace entirely:
from utils import *
现在,谁知道要导入什么符号:基本上utils
必须提供的所有内容(或者,如果utils
开发人员麻烦地指定了__all__
属性,则列出的所有内容).我建议您仅将import *
用于快速和肮脏的编程.
Now, who knows what symbols have been imported: basically everything that utils
has to offer the world (or, if the utils
developer took the trouble to specify an __all__
attribute, then everything listed there). I'd advise you to use import *
only for quick-and-dirty programming, if at all.
这实际上是从命名空间角度最接近execfile
的导入样式:execfile('utils.py')
的作用与from utils import *
相同,因为它会将utils
所定义的所有符号转储到您的计算机中.工作区.略有不同是,execfile
甚至不会将自己限制为__all__
中的符号-实际上,__all__
符号本身只会与其他所有内容一起丢在您的腿上.
This is actually the importing style that is closest to execfile
from the namespace point of view: execfile('utils.py')
does much the same as from utils import *
in that it dumps all symbols defined by utils
willy-nilly into your workspace. One slight difference is that execfile
won't even limit itself to the symbols in __all__
if that is defined—in fact, the __all__
symbol itself will just get dumped in your lap along with everything else.
除名称空间外,from utils import *
和execfile('utils.py')
之间仍然存在许多差异.一个正在缓存:对utils
的第二次import
调用将非常快(该代码将不会重新运行),但是对execfile('utils.py')
的第二次调用可能与第一次调用一样长,因为代码将重新运行.另外,在utils.py
中可能有一些代码(通常是测试代码),utils
作者不希望在导入时运行,而当通过execfile
执行文件时,该代码仅为 .此类代码放在if __name__ == '__main__':
子句中.
Beyond namespaces, there are still plenty of differences between from utils import *
and execfile('utils.py')
. One is caching: a second import
call on utils
will be very fast (the code will not be re-run), but a second call to execfile('utils.py')
may take just as long as the first because the code will be re-run. Also, there may be some code (often test code) inside utils.py
that the utils
author does not want to run at import time, but only when the file is executed via execfile
. Such code is placed inside an if __name__ == '__main__':
clause.
这篇关于导入和execfile之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!