作为在正常情况下使用内置__import__()
问题的后续,我进行了一些测试,并遇到了令人惊讶的结果。
我在这里比较了传统的< code>import语句和对< code>__import__内置函数的调用的执行时间。为此,我在交互模式下使用以下脚本:
import timeit
def test(module):
t1 = timeit.timeit("import {}".format(module))
t2 = timeit.timeit("{0} = __import__('{0}')".format(module))
print("import statement: ", t1)
print("__import__ function:", t2)
print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))
与链接的问题一样,这里是导入sys
以及其他一些标准模块时的比较:
>>> test('sys')
import statement: 0.319865173171288
__import__ function: 0.38428380458522987
t(statement) < t(function)
>>> test('math')
import statement: 0.10262547545597034
__import__ function: 0.16307580163101054
t(statement) < t(function)
>>> test('os')
import statement: 0.10251490255312312
__import__ function: 0.16240755669640627
t(statement) < t(function)
>>> test('threading')
import statement: 0.11349136644972191
__import__ function: 0.1673617034957573
t(statement) < t(function)
到目前为止,import
比__import__()
更快。这对我来说很有意义,因为正如我在链接的帖子中所写的那样,我发现与CALL_FUNCTION
相比,当后者导致对__IMPORT_
的调用时,对IMPORT_NAME
指令进行优化是合乎逻辑的。
但是当涉及到不太标准的模块时,结果正好相反:
>>> test('numpy')
import statement: 0.18907936340054476
__import__ function: 0.15840019037769792
t(statement) > t(function)
>>> test('tkinter')
import statement: 0.3798560809537861
__import__ function: 0.15899962771786136
t(statement) > t(function)
>>> test("pygame")
import statement: 0.6624641952621317
__import__ function: 0.16268579177259568
t(statement) > t(function)
执行时间差异背后的原因是什么?import
语句在标准模块上更快的实际原因是什么?另一方面,为什么__import_
函数与其他模块相比更快?
测试从Python 3.6开始
执行时间的差异背后的原因是什么?
导入语句有一个非常简单的路径。它导致IMPORT_NAME
调用import_name
并导入给定的模块(如果没有覆盖名称__import__
):
dis('import math')
1 0 LOAD_CONST 0 (0)
2 LOAD_CONST 1 (None)
4 IMPORT_NAME 0 (math)
6 STORE_NAME 0 (math)
8 LOAD_CONST 1 (None)
10 RETURN_VALUE
另一方面,__import__
通过所有函数通过CALL_FUNCTION
执行的泛型函数调用步骤:
dis('__import__(math)')
1 0 LOAD_NAME 0 (__import__)
2 LOAD_NAME 1 (math)
4 CALL_FUNCTION 1
6 RETURN_VALUE
当然,它是内置的,比普通的py函数快得多,但它仍然比带有import_name
的import
语句慢。
这就是为什么它们之间的时间差是恒定的。使用@MSeifert片段(纠正了不公平的时间:-)并添加另一个打印,您可以看到以下内容:
import timeit
def test(module):
exec("import {}".format(module))
t2 = timeit.timeit("{0} = __import__('{0}')".format(module))
t1 = timeit.timeit("import {}".format(module))
print("import statement: ", t1)
print("__import__ function:", t2)
print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))
print('Diff: {}'.format(t2-t1))
for m in sys.builtin_module_names:
test(m)
在我的机器上,它们之间有大约0.17的恒定差异(通常预期有轻微差异)
*值得注意的是,这些并不完全等价。__import__
不做任何名称绑定,正如字节码所证明的那样。
请记住,所有模块在第一次导入后都会缓存到< code>sys.modules中,因此...
无论如何,我的结果如下所示:
#!/bin/bash
itest() {
echo -n "import $1: "
python3 -m timeit "import $1"
echo -n "__import__('$1'): "
python3 -m timeit "__import__('$1')"
}
itest "sys"
itest "math"
itest "six"
itest "PIL"
导入系统
: 0.481__import__('sys')
: 0.586导入数学
:0.163__import__('数学')
: 0.247导入六
: 0.157__import__('六')
: 0.273导入PIL
: 0.162__import__('PIL')
: 0.265timeit
测量总执行时间,但模块的第一次导入(无论是通过导入还是__import__
)都比后续导入慢 - 因为它是唯一实际执行模块初始化的导入
。它必须在文件系统中搜索模块的文件,加载模块的源代码(最慢)或以前创建的字节码(慢但比解析.py
文件快一点)或共享库(对于 C 扩展),执行初始化代码,并将模块对象存储在 sys.modules
中。后续导入将跳过所有这些并从 sys.modules
中检索模块对象。
如果颠倒顺序,结果将不同:
import timeit
def test(module):
t2 = timeit.timeit("{0} = __import__('{0}')".format(module))
t1 = timeit.timeit("import {}".format(module))
print("import statement: ", t1)
print("__import__ function:", t2)
print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))
test('numpy')
import statement: 0.4611093703134608
__import__ function: 1.275512785926014
t(statement) < t(function)
获得无偏差结果的最好方法是导入一次,然后进行计时:
import timeit
def test(module):
exec("import {}".format(module))
t2 = timeit.timeit("{0} = __import__('{0}')".format(module))
t1 = timeit.timeit("import {}".format(module))
print("import statement: ", t1)
print("__import__ function:", t2)
print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))
test('numpy')
import statement: 0.4826306561727307
__import__ function: 0.9192819125911029
t(statement) < t(function)
所以,是的,导入
总是比__import__
快。
通过运行下面的代码,我可以直接与if语句进行比较,速度几乎是使用max函数的4倍。 我试图理解这背后的原因。 对比:0.63秒,最大:2.3秒
每个spark程序都有这行。当我上网了解scala中“implicits”的用法时,我得到了这样的定义: 我明白这个定义,但它给我带来了以下的疑问。 其他导入语句不也是这样吗?每个import语句都会带来我们希望在代码中使用的函数/选项/方法。如果与常规导入语句不同,那么它们给表带来了什么?它们有何不同?谁能解释一下scala中参数和函数的真正用例吗?
问题内容: 有人可以向我解释该声明的工作方式吗? 例如,我在包中有一个类型: 我的包裹中有一个类型: 这给了我以下错误: 我试图将导入更改为以下代码: 但是得到这个错误: 我也不明白。那么,和之间有什么区别?如何正确设置我的模型? 问题答案: 每个包都有一组类型,函数,变量等。我们将它们称为 实体 。每个实体可以导出(名称以大写字母开头),也可以不导出(名称以小写字母开头)。 一个包只能访问另一个
如果你想要直接输入argv变量到你的程序中(避免在每次使用它时打sys.),那么你可以使用from sys import argv语句。如果你想要输入所有sys模块使用的名字,那么你可以使用from sys import *语句。这对于所有模块都适用。一般说来,应该避免使用from..import而使用import语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。
问题内容: 在Python中使用IF语句时,必须执行以下操作才能使“层叠”正常工作。 检查“等于”时,是否有办法使Python接受多个值?例如, 问题答案: if job in (“mechanic”, “tech”): print “awesome” elif job in (“tool”, “rock”): print “dolt” 括号中的值是一个元组。该运营商检查,看是否右手柄元组内的某处