Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python在函数级与模块级导入_Python_Import_Scope - Fatal编程技术网

Python在函数级与模块级导入

Python在函数级与模块级导入,python,import,scope,Python,Import,Scope,如果有疑问,我通常会将导入语句放在模块的顶部。通常,这会减少重复,这很好。但是,在只有一个函数(或类)需要导入的情况下,是否存在性能下降 以下内容是否仅在调用函数时导入 def func(): from task import test 如果是这样,我想这可能是一个轻微的效率。我还假设您可以获得一些附加点,以加快垃圾收集和变量作用域,因为导入的对象不会添加到全局字典中。正如另一张海报所说: 这主要是由于变量查找。在全局范围内查找变量需要字典查找。相反,编译器静态地确

如果有疑问,我通常会将导入语句放在模块的顶部。通常,这会减少重复,这很好。但是,在只有一个函数(或类)需要导入的情况下,是否存在性能下降

以下内容是否仅在调用函数时导入

     def func():
         from task import test
如果是这样,我想这可能是一个轻微的效率。我还假设您可以获得一些附加点,以加快垃圾收集和变量作用域,因为导入的对象不会添加到全局字典中。正如另一张海报所说:

这主要是由于变量查找。在全局范围内查找变量需要字典查找。相反,编译器静态地确定本地名称,并通过索引引用它们,因此不需要查找字典

这些假设是否合理?我是否完全偏离了基准


谢谢

让我们看看以下两个函数的字节码:

def func1():
    """ test imported each time function is run """
    from task import test
    test()

def func2():
    """ test was imported at top of module """
    test()
如下所示,
func2()
通过使用全局导入的
test
函数节省了大量步骤

>>> dis.dis(func1)
  3           0 LOAD_CONST               1 (-1)
              3 LOAD_CONST               2 (('test',))
              6 IMPORT_NAME              0 (task)
              9 IMPORT_FROM              1 (test)
             12 STORE_FAST               0 (test)
             15 POP_TOP

  4          16 LOAD_FAST                0 (test)
             19 CALL_FUNCTION            0
             22 POP_TOP
             23 LOAD_CONST               3 (None)
             26 RETURN_VALUE
>>> dis.dis(func2)
  3           0 LOAD_GLOBAL              0 (test)
              3 CALL_FUNCTION            0
              6 POP_TOP
              7 LOAD_CONST               1 (None)
             10 RETURN_VALUE
正如德尔南在评论中指出的那样,预先考虑到这一点可能是过早的优化


至于
test
位于全局命名空间中,这不太可能导致任何查找性能问题。我认为您可以看到这一点的最显著方式是,如果
test
与您经常使用的另一个名称发生哈希冲突,这会导致查找第二个名称的时间更长。再次,过早的优化来考虑前面的罕见情况。

< P>我认为如果不经常调用,将导入放在定义中是有意义的。

< P>函数中的导入仅在函数运行时才导入。请记住,在Python中,所有语句都是在遇到它们时执行的,导入语句与其他语句一样。顶级导入是在导入模块时导入的,因为它们是模块中的顶级语句

您对名称查找的担忧是错误的:差异可以忽略不计,只有在分析显示问题时才应该考虑


我只将模块导入到函数范围中有两个原因:1)修复循环导入问题,顺便说一句,这可能可以通过重构以其他方式解决;或者2)如果模块是可选的,并且函数没有被我的许多用户使用。在2)的情况下,模块可能完全丢失,除非有人调用该函数,否则不会出现问题。

至于名称查找性能:这无关紧要。在极少数情况下,它会这样做,你会发现当你完成代码,发现它太慢,并分析。但请注意,它实际上不会导入模块不止一次-它只是检查是否是必须的,每次调用它。感谢你这样布置它;这很有用。不熟悉dis库。这更多的是一个理论问题。似乎有区别,即使可以忽略。谢谢,内德,这是最有吸引力的方式吗?我看到一些人在模块根目录的init.py上进行导入,然后从那里导入所有内容。这可以用来解决某些循环进口问题吗?
>>> dis.dis(func1)
  3           0 LOAD_CONST               1 (-1)
              3 LOAD_CONST               2 (('test',))
              6 IMPORT_NAME              0 (task)
              9 IMPORT_FROM              1 (test)
             12 STORE_FAST               0 (test)
             15 POP_TOP

  4          16 LOAD_FAST                0 (test)
             19 CALL_FUNCTION            0
             22 POP_TOP
             23 LOAD_CONST               3 (None)
             26 RETURN_VALUE
>>> dis.dis(func2)
  3           0 LOAD_GLOBAL              0 (test)
              3 CALL_FUNCTION            0
              6 POP_TOP
              7 LOAD_CONST               1 (None)
             10 RETURN_VALUE