Reputation: 39
For example import math
import's all function in math module whereas if we write from math import sqrt,pow
then only sqrt(),pow()
are imported.
Is their any performance or memory difference in both of them.
Upvotes: 1
Views: 304
Reputation: 126837
For example
import math
import's all function in math module whereas if we writefrom math import sqrt,pow
then onlysqrt(),pow()
are imported.
It's a bit more complicated than that.
If we ignore for a moment that the math
is built in into the interpreter (so there's nothing that has to be actually loaded), whether you do import math
, from math import sqrt, pow
or from math import *
, the whole math
module is loaded anyhow, and, after the import statement, it is present in sys.modules
. So, it's not like there's more or less work to do for loading depending from how you import it.
The only difference between these constructs is the creation, in the import scope, of references to the names you mention in the import statement.
import math
is probably the cheapest statement by itself, as it loads the module and just adds a local reference to the module object in the current scope; it essentially boils down to doing
math = __import__('math')
However, each usage is going to be more costly, as math.sin
will need two dict lookups (one LOAD_GLOBAL
and one LOAD_ATTR
) if the import
was at global scope, or one local variable lookup (LOAD_FAST
) + one dict lookup (LOAD_ATTR
) (if it was imported locally to a function) to actually reach the function object to invoke.
from math import sqrt, pow
will cost a bit more, as it needs to load the module, look up sqrt
and pow
in it (two dict lookups) and create the corresponding entries in the scope where you imported them (two dict assignment if in global scope, two STORE_FAST
local assignments if in function scope). It is equivalent to something like:
__temp = __import__('math')
sqrt = __temp.sqrt
pow = __temp.pow
del __temp
(__temp
does not really exist, it's going to be just an object on the stack; sqrt
and pow
will be locals or globals depending from where the import
statement has been issued)
On the other hand, on lookup this is going to be faster, as it needs only one dict lookup (LOAD_GLOBAL
for global import) or one local lookup (LOAD_FAST
for import local to a function) compared to the two above.
from math import *
is the same as above, but for all the symbols provided in the module __all__
list (or all the symbols provided by the module period if no __all__
is specified).
From a memory standpoint, the latter two are going to cost more than the first, as they create more entries in the locals list or in the globals dict.
That being said, this kind of consideration is generally completely irrelevant, as we are talking about extremely small differences; what matters most when deciding how to import is how much pollution to your namespace is fine to allow in the name of less typing/less explicit imports.
Instead, the kind of optimization in these matters that usually counts is to bind frequently called functions to local variables to avoid continuous lookups in inner loops; for example
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)))
is generally going to be faster than doing math.sin
and math.cos
at each iteration, or even than importing sin
and cos
at top level in the file and using them straight inside the loop, as they are respectively two or one dict lookup away (to be done at each iteration), while here the interpreter just has to load two locals in the inner loop (which is very fast, it's just a straight array load).
Upvotes: 4