在Python中,当您在函数中导入时会发生什么?(复制)

时间:2022-11-22 20:58:19

This question already has an answer here:

这个问题已经有了答案:

What are the pros and cons of importing a Python module and/or function inside of a function, with respect to efficiency of speed and of memory?

在函数中导入Python模块和/或函数,在速度和内存效率方面有什么优点和缺点?

Does it re-import every time the function is run, or perhaps just once at the beginning whether or not the function is run?

它是在每次运行函数时重新导入,还是在开始时重新导入一次?

6 个解决方案

#1


93  

Does it re-import every time the function is run?

它是否在每次运行函数时重新导入?

No; or rather, Python modules are essentially cached every time they are imported, so importing a second (or third, or fourth...) time doesn't actually force them to go through the whole import process again.

没有;或者更确切地说,Python模块在每次导入时都被缓存,因此,导入第二个(或第三个,或第四个…)时间实际上不会迫使它们再次执行整个导入过程。

Does it import once at the beginning whether or not the function is run?

不管函数是否运行,它是否在开始时导入一次?

No, it is only imported if and when the function is executed.

不,它只在函数执行时导入。

As for the benefits: it depends, I guess. If you may only run a function very rarely and don't need the module imported anywhere else, it may be beneficial to only import it in that function. Or if there is a name * or other reason you don't want the module or symbols from the module available everywhere, you may only want to import it in a specific function. (Of course, there's always from my_module import my_function as f for those cases.)

至于好处:我想这得看情况。如果您可能只很少运行函数,并且不需要将模块导入到其他任何地方,那么最好只在该函数中导入它。或者,如果有名称冲突或其他原因,您不希望模块或符号在任何地方都可用,您可能只希望在特定的函数中导入它。(当然,在这些情况下,my_module总是将my_function作为f导入。)

In general practice, it's probably not that beneficial. In fact, most Python style guides encourage programmers to place all imports at the beginning of the module file.

一般来说,这可能没有什么好处。实际上,大多数Python样式指南鼓励程序员在模块文件的开头放置所有导入。

#2


33  

The very first time you import goo from anywhere (inside or outside a function), goo.py (or other importable form) is loaded and sys.modules['goo'] is set to the module object thus built. Any future import within the same run of the program (again, whether inside or outside a function) just look up sys.modules['goo'] and bind it to barename goo in the appropriate scope. The dict lookup and name binding are very fast operations.

第一次从任何地方(函数内部或外部)导入goo时,goo。加载py(或其他可输入的表单)和sys。模块['goo']被设置为这样构建的模块对象。在程序的相同运行过程中(同样,无论是函数内部还是函数外部)的任何未来导入都只需要查找sys。模块['goo']并在适当的范围内将其绑定到barename goo。命令查找和名称绑定是非常快的操作。

Assuming the very first import gets totally amortized over the program's run anyway, having the "appropriate scope" be module-level means each use of goo.this, goo.that, etc, is two dict lookups -- one for goo and one for the attribute name. Having it be "function level" pays one extra local-variable setting per run of the function (even faster than the dictionary lookup part!) but saves one dict lookup (exchanging it for a local-variable lookup, blazingly fast) for each goo.this (etc) access, basically halving the time such lookups take.

假设第一个导入在程序运行过程中被完全平摊,拥有“适当的范围”是模块级意味着每次使用goo。这个,咕。这是两个dict类型查找——一个用于goo,一个用于属性名称。让它是“函数级”会在每次函数运行时额外增加一个局部变量设置(甚至比字典查找部分还要快!),但是会为每个goo保存一个dict类型查找(将它替换为局部变量查找,非常快)。这个(等等)访问,基本上是将这种查找所需的时间减半。

We're talking about a few nanoseconds one way or another, so it's hardly a worthwhile optimization. The one potentially substantial advantage of having the import within a function is when that function may well not be needed at all in a given run of the program, e.g., that function deals with errors, anomalies, and rare situations in general; if that's the case, any run that does not need the functionality will not even perform the import (and that's a saving of microseconds, not just nanoseconds), only runs that do need the functionality will pay the (modest but measurable) price.

我们讨论的是几纳秒,所以这不是一个值得的优化。在函数中引入导入的一个潜在的重要优势是,在给定的程序运行中,该函数很可能根本不需要这个函数,例如,该函数处理错误、异常和一般的罕见情况;如果是这样的话,任何不需要功能的运行都不会执行导入操作(这是一种节省的微秒,而不仅仅是纳秒),只有需要功能的运行才会支付(适度但可测量的)价格。

It's still an optimization that's only worthwhile in pretty extreme situations, and there are many others I would consider before trying to squeeze out microseconds in this way.

这仍然是一种只有在非常极端的情况下才值得进行的优化,在以这种方式挤出微秒之前,我还要考虑许多其他的优化。

#3


9  

It imports once when the function executes first time.

当函数第一次执行时,它将导入一次。

Pros:

优点:

  • imports related to the function they're used in
  • 与所使用的函数相关的导入。
  • easy to move functions around the package
  • 很容易在包中移动函数

Cons:

缺点:

  • couldn't see what modules this module might depend on
  • 不知道这个模块可能依赖什么模块

#4


5  

Importing inside a function will effectively import the module once.. the first time the function is run.

在函数内导入,模块一次有效导入。第一次运行函数。

It ought to import just as fast whether you import it at the top, or when the function is run. This isn't generally a good reason to import in a def. Pros? It won't be imported if the function isn't called.. This is actually a reasonable reason if your module only requires the user to have a certain module installed if they use specific functions of yours...

无论在顶部导入,还是在运行函数时,它的导入速度都应该一样快。这通常不是在def中导入的一个好理由。如果函数不被调用,它就不会被导入。这实际上是一个合理的理由,如果您的模块只要求用户安装某个模块,如果他们使用您的特定功能……

If that's not he reason you're doing this, it's almost certainly a yucky idea.

如果他不是你这么做的理由,那么这几乎肯定是一个恶心的想法。

#5


3  

Might I suggest in general that instead of asking, "Will X improve my performance?" you use profiling to determine where your program is actually spending its time and then apply optimizations according to where you'll get the most benefit?

我是否可以建议大家不要问“X会提高我的性能吗?”,而是使用分析来确定程序的实际花费时间,然后根据您将获得的最大好处应用优化?

And then you can use profiling to assure that your optimizations have actually benefited you, too.

然后,您可以使用profiling来确保您的优化实际上也使您受益。

#6


2  

It imports once when the function is called for the first time.

当函数第一次调用时,它会导入一次。

I could imagine doing it this way if I had a function in an imported module that is used very seldomly and is the only one requiring the import. Looks rather far-fetched, though...

我可以这样想象,如果我在一个导入的模块中有一个函数,这个函数使用的非常少,并且是唯一一个需要导入的函数。看起来相当牵强,尽管……

#1


93  

Does it re-import every time the function is run?

它是否在每次运行函数时重新导入?

No; or rather, Python modules are essentially cached every time they are imported, so importing a second (or third, or fourth...) time doesn't actually force them to go through the whole import process again.

没有;或者更确切地说,Python模块在每次导入时都被缓存,因此,导入第二个(或第三个,或第四个…)时间实际上不会迫使它们再次执行整个导入过程。

Does it import once at the beginning whether or not the function is run?

不管函数是否运行,它是否在开始时导入一次?

No, it is only imported if and when the function is executed.

不,它只在函数执行时导入。

As for the benefits: it depends, I guess. If you may only run a function very rarely and don't need the module imported anywhere else, it may be beneficial to only import it in that function. Or if there is a name * or other reason you don't want the module or symbols from the module available everywhere, you may only want to import it in a specific function. (Of course, there's always from my_module import my_function as f for those cases.)

至于好处:我想这得看情况。如果您可能只很少运行函数,并且不需要将模块导入到其他任何地方,那么最好只在该函数中导入它。或者,如果有名称冲突或其他原因,您不希望模块或符号在任何地方都可用,您可能只希望在特定的函数中导入它。(当然,在这些情况下,my_module总是将my_function作为f导入。)

In general practice, it's probably not that beneficial. In fact, most Python style guides encourage programmers to place all imports at the beginning of the module file.

一般来说,这可能没有什么好处。实际上,大多数Python样式指南鼓励程序员在模块文件的开头放置所有导入。

#2


33  

The very first time you import goo from anywhere (inside or outside a function), goo.py (or other importable form) is loaded and sys.modules['goo'] is set to the module object thus built. Any future import within the same run of the program (again, whether inside or outside a function) just look up sys.modules['goo'] and bind it to barename goo in the appropriate scope. The dict lookup and name binding are very fast operations.

第一次从任何地方(函数内部或外部)导入goo时,goo。加载py(或其他可输入的表单)和sys。模块['goo']被设置为这样构建的模块对象。在程序的相同运行过程中(同样,无论是函数内部还是函数外部)的任何未来导入都只需要查找sys。模块['goo']并在适当的范围内将其绑定到barename goo。命令查找和名称绑定是非常快的操作。

Assuming the very first import gets totally amortized over the program's run anyway, having the "appropriate scope" be module-level means each use of goo.this, goo.that, etc, is two dict lookups -- one for goo and one for the attribute name. Having it be "function level" pays one extra local-variable setting per run of the function (even faster than the dictionary lookup part!) but saves one dict lookup (exchanging it for a local-variable lookup, blazingly fast) for each goo.this (etc) access, basically halving the time such lookups take.

假设第一个导入在程序运行过程中被完全平摊,拥有“适当的范围”是模块级意味着每次使用goo。这个,咕。这是两个dict类型查找——一个用于goo,一个用于属性名称。让它是“函数级”会在每次函数运行时额外增加一个局部变量设置(甚至比字典查找部分还要快!),但是会为每个goo保存一个dict类型查找(将它替换为局部变量查找,非常快)。这个(等等)访问,基本上是将这种查找所需的时间减半。

We're talking about a few nanoseconds one way or another, so it's hardly a worthwhile optimization. The one potentially substantial advantage of having the import within a function is when that function may well not be needed at all in a given run of the program, e.g., that function deals with errors, anomalies, and rare situations in general; if that's the case, any run that does not need the functionality will not even perform the import (and that's a saving of microseconds, not just nanoseconds), only runs that do need the functionality will pay the (modest but measurable) price.

我们讨论的是几纳秒,所以这不是一个值得的优化。在函数中引入导入的一个潜在的重要优势是,在给定的程序运行中,该函数很可能根本不需要这个函数,例如,该函数处理错误、异常和一般的罕见情况;如果是这样的话,任何不需要功能的运行都不会执行导入操作(这是一种节省的微秒,而不仅仅是纳秒),只有需要功能的运行才会支付(适度但可测量的)价格。

It's still an optimization that's only worthwhile in pretty extreme situations, and there are many others I would consider before trying to squeeze out microseconds in this way.

这仍然是一种只有在非常极端的情况下才值得进行的优化,在以这种方式挤出微秒之前,我还要考虑许多其他的优化。

#3


9  

It imports once when the function executes first time.

当函数第一次执行时,它将导入一次。

Pros:

优点:

  • imports related to the function they're used in
  • 与所使用的函数相关的导入。
  • easy to move functions around the package
  • 很容易在包中移动函数

Cons:

缺点:

  • couldn't see what modules this module might depend on
  • 不知道这个模块可能依赖什么模块

#4


5  

Importing inside a function will effectively import the module once.. the first time the function is run.

在函数内导入,模块一次有效导入。第一次运行函数。

It ought to import just as fast whether you import it at the top, or when the function is run. This isn't generally a good reason to import in a def. Pros? It won't be imported if the function isn't called.. This is actually a reasonable reason if your module only requires the user to have a certain module installed if they use specific functions of yours...

无论在顶部导入,还是在运行函数时,它的导入速度都应该一样快。这通常不是在def中导入的一个好理由。如果函数不被调用,它就不会被导入。这实际上是一个合理的理由,如果您的模块只要求用户安装某个模块,如果他们使用您的特定功能……

If that's not he reason you're doing this, it's almost certainly a yucky idea.

如果他不是你这么做的理由,那么这几乎肯定是一个恶心的想法。

#5


3  

Might I suggest in general that instead of asking, "Will X improve my performance?" you use profiling to determine where your program is actually spending its time and then apply optimizations according to where you'll get the most benefit?

我是否可以建议大家不要问“X会提高我的性能吗?”,而是使用分析来确定程序的实际花费时间,然后根据您将获得的最大好处应用优化?

And then you can use profiling to assure that your optimizations have actually benefited you, too.

然后,您可以使用profiling来确保您的优化实际上也使您受益。

#6


2  

It imports once when the function is called for the first time.

当函数第一次调用时,它会导入一次。

I could imagine doing it this way if I had a function in an imported module that is used very seldomly and is the only one requiring the import. Looks rather far-fetched, though...

我可以这样想象,如果我在一个导入的模块中有一个函数,这个函数使用的非常少,并且是唯一一个需要导入的函数。看起来相当牵强,尽管……