Python 为什么是;从…起进口*”;在不允许的函数中?

Python 为什么是;从…起进口*”;在不允许的函数中?,python,function,python-3.x,python-import,Python,Function,Python 3.x,Python Import,发件人: 仅允许在模块级别使用通配符形式的导入-自模块导入*。试图在类或函数定义中使用它将引发语法错误 为什么??避免在函数中使用它有什么意义?问题出在哪里?CPython实现对局部变量使用了一种特殊的优化:它们不像全局变量那样在运行时从字典中动态查找,而是在编译时静态分配索引,并在运行时通过索引查找,这要快得多。这要求Python编译器能够在编译时识别所有的本地名称,如果在函数级有通配符导入,这是不可能的 在Python2中,仍然存在一种回退机制,在无法始终静态确定所有本地名称的情况下调用该机

发件人:

仅允许在模块级别使用通配符形式的导入-
自模块导入*
。试图在类或函数定义中使用它将引发
语法错误


为什么??避免在函数中使用它有什么意义?问题出在哪里?

CPython实现对局部变量使用了一种特殊的优化:它们不像全局变量那样在运行时从字典中动态查找,而是在编译时静态分配索引,并在运行时通过索引查找,这要快得多。这要求Python编译器能够在编译时识别所有的本地名称,如果在函数级有通配符导入,这是不可能的

在Python2中,仍然存在一种回退机制,在无法始终静态确定所有本地名称的情况下调用该机制。这种机制为局部变量使用了动态字典,大大降低了执行速度

例如,此代码

def f():
    exec "x = 2"
    print x
在Python2中按预期工作,而

def f():
    exec("x = 2")
    print(x)

结果在Python3中出现
NameError

因此,如果我得到正确的方法:在编译期间,对于局部作用域,Python将查找所有使用的变量并将其存储在表中;相反,对于globals,Python在运行时修改包含所有全局名称的字典。在函数中,我们不能使用通配符,因为使用Python作为静态机制,它应该查找并编译在函数中导入的所有模块以及在这些模块中导入的模块。是吗?@antox:是的,没错。由于全局变量是动态的,它们甚至可以在运行时动态创建,例如通过修改
globals()
字典或使用
exec()
,因此完全不可能静态确定所有可能导入的名称。@sven_marnach好的,只有一个问题。你说过在Python2中他们使用了双重机制,第一种是静态机制,第二种是动态机制,作为后备机制。难道他们不能对全球人也使用这种行为吗?因为我知道“静态”优化程序,所以他们使用静态策略,但如果你想执行
exec(“x=2”)
引擎会采用第二种策略,是动态机制变慢了,还是从静态机制切换到动态机制的整个机制变慢了?@antox:如果不改变语言语义,对全局语言实现这一点是很困难的。例如,您必须静态检测是否有人正在调用
globals()
。此外,由于循环中的大多数变量查找都是针对局部变量的,因此对全局变量的回报可能会更低。如果您想对代码进行微优化,可以将全局变量提升到全局范围。