python - 导入给定模块的所有功能与仅导入我们需要的那些功能之间的内存和性能差异是什么?
问题描述
例如 import math
在数学模块中导入的所有功能,而如果我们编写 from math import sqrt,pow
则只sqrt(),pow()
被导入。
他们两者的任何性能或内存差异。
解决方案
例如
import math
在数学模块中导入的所有功能,而如果我们编写from math import sqrt,pow
则只sqrt(),pow()
被导入。
比这复杂一点。
如果我们暂时忽略math
解释器中内置的(因此实际上不需要加载任何内容),无论您是否执行或import math
,无论如何都会加载整个模块,并且在 import 语句之后,它存在于. 因此,根据您导入的方式,加载工作并没有或多或少的工作要做。from math import sqrt, pow
from math import *
math
sys.modules
这些构造之间的唯一区别是在导入范围内创建对您在导入语句中提到的名称的引用。
import math
本身可能是最便宜的语句,因为它加载模块并只是在当前范围内添加对模块对象的本地引用;它基本上归结为做
math = __import__('math')
但是,每次使用都会更加昂贵,因为如果是在全局范围内,math.sin
则需要两个 dict 查找(一个LOAD_GLOBAL
和一个) ,或者一个局部变量查找()+一个 dict 查找()(如果它是在本地导入到function) 来实际到达要调用的函数对象。LOAD_ATTR
import
LOAD_FAST
LOAD_ATTR
from math import sqrt, pow
将花费更多,因为它需要加载模块,查找sqrt
并pow
在其中(两个字典查找)并在导入它们的范围内创建相应的条目(如果在全局范围内,则两个字典分配,STORE_FAST
如果在功能范围)。它相当于:
__temp = __import__('math')
sqrt = __temp.sqrt
pow = __temp.pow
del __temp
(__temp
实际上并不存在,它将只是堆栈上的一个对象;sqrt
并且pow
将是局部变量或全局变量,具体取决于import
发出语句的位置)
另一方面,在查找时这会更快,因为与上述两个相比,它只需要一个 dict 查找(LOAD_GLOBAL
用于全局导入)或一个本地查找(用于导入本地到函数)。LOAD_FAST
from math import *
与上述相同,但针对模块__all__
列表中提供的所有符号(或模块周期提供的所有符号,如果未__all__
指定)。
从内存的角度来看,后两个将比第一个花费更多,因为它们在本地列表或全局字典中创建了更多条目。
话虽如此,这种考虑通常是完全无关的,因为我们谈论的是极小的差异;在决定如何导入时,最重要的是允许以较少输入/较少显式导入的名义对命名空间造成多少污染。
相反,在这些问题上通常很重要的优化是将经常调用的函数绑定到局部变量,以避免在内部循环中连续查找;例如
import math
def plot_it(framebuffer):
sin = math.sin
cos = math.cos
for y in range(1024):
for x in range(1024):
framebuffer[y][x] = int(127*(sin(x)+cos(2*y)))
通常会比做math.sin
和math.cos
在每次迭代时更快,甚至比在文件的顶层导入sin
和直接在循环内使用它们要快,因为它们分别是两个或一个字典查找(在每次迭代中完成) cos
,而这里的解释器只需要在内部循环中加载两个本地变量(这非常快,它只是一个直接的数组加载)。
推荐阅读
- swift - 如何解决 Swift 中 oAuth 的 Firebase 错误。FIRAuthError 域代码=17999
- javascript - 包含 JSP/JS 的 Python Beautiful Soup 抓取页面
- c# - ZXing .Net - 无法解码/读取图像中的任何条形码
- webpack - 未知属性“优化”
- jsch - 从 SSH 服务器到目标主机的安全隧道
- c# - 调用 wcf 方法时通知 rabbitmq 队列订阅者
- python - 如何在类内部但在方法外部引用python类变量?
- android - 在 Android 中通过 Retrofit 库使用 API
- react-native - 如何动态分配每个按钮以在单击时更改颜色
- ios - 即使禁用 contentInset Xcode 9.4.1,UITableView 仍然在顶部留下空间