Например, import math
все функции импорта в математическом модуле, тогда как если мы пишем from math import sqrt,pow
, то импортируются только sqrt(),pow()
.
Это немного сложнее.
Если на мгновение мы проигнорируем, что math
встроен в интерпретатор (так что нет ничего, что действительно нужно загружать), независимо от того, выполняете ли вы import math
, from math import sqrt, pow
или from math import *
,Весь модуль math
загружается в любом случае, и после оператора импорта он присутствует в sys.modules
.Таким образом, это не значит, что для загрузки требуется больше или меньше работы в зависимости от того, как вы ее импортируете.
Единственное различие между этими конструкциями заключается в создании в области импорта ссылок.к именам, которые вы упоминаете в операторе импорта.
import math
, вероятно, самый дешевый оператор сам по себе , поскольку он загружает модуль и просто добавляет локальную ссылку на объект модуля втекущая сфера применения;по сути, это сводится к выполнению
math = __import__('math')
Однако каждое использование будет более дорогостоящим, так как math.sin
потребуется два поиска в режиме dict (один LOAD_GLOBAL
и один LOAD_ATTR
), если import
находился в глобальной области видимости, или один поиск локальной переменной (LOAD_FAST
) + один поиск в двоичном формате (LOAD_ATTR
) (если он был импортирован локально в функцию) для фактического достижения объекта функции для вызова.
from math import sqrt, pow
будет стоить немного дороже, так как для него потребуется загрузить модуль, найдите в нем sqrt
и pow
(два поиска в dict) и создайте соответствующие записи в области, в которую вы их импортировали (если в двухкратном назначении)в глобальной области видимости два 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
на верхнем уровне в файле и использовать ихпрямо в цикле, так как они, соответственно, два или один продиктованный поиск (для каждой итерации), в то время как здесь интерпретатору просто нужно загрузить два локальных объекта во внутреннем цикле (что очень быстро, это просто прямая загрузка массива)).