SystemError 在尝试在运行时在其他函数中使用仅位置参数创建函数后引发
SystemError is raised after attempt to create function with positional-only args in runtime inside other one
有一些测试代码:
some_type = int
def func0():
def func1(arg: some_type, /):
pass
func0()
我收到以下错误:
Traceback (most recent call last):
...
SystemError: no locals when loading 'some_type'
但是下面的代码按预期工作:
some_type = int
def func0():
def func1(arg: some_type):
pass
func0()
这个也是有效的:
some_type = int
exec('''
def func1(arg: some_type, /):
pass
''')
我知道在未来的版本中将不再在定义时评估注释;也可以在 3.7+ 版本中激活此类行为。像
from __future__ import annotations
some_type = int
def func0():
def func1(arg: some_type, /):
pass
func0()
也没有问题。但是,问题是关于函数定义时当前的奇怪行为。 some_type
绝不是 func0
的局部变量,尽管 python 这么认为。又一精良版:
def func0():
some_type = int
def func1(arg: some_type, /):
pass
func0()
我读过 PEP 570 但没有找到任何关于注解声明的内容。
我的python版本:
sys.version_info(major=3, minor=8, micro=0, releaselevel='final', serial=0)
这是 cpython 中的一个错误——我已经在这里打开了一个问题:https://bugs.python.org/issue39215
查看这两个函数的反汇编,它似乎在构建注释类型时错误地使用了 LOAD_NAME
而不是 LOAD_GLOBAL
-- 这是仅具有和不具有位置的区别参数:
$ diff -u <(python3.9 -m dis t2.py | sed 's/0x[a-f0-9]*/0xdeadbeef/g;s/t2\.py/FILENAME/g') <(python3.9 -m dis t3.py | sed 's/0x[a-f0-9]*/0xdeadbeef/g;s/t3\.py/FILENAME/g')
--- /dev/fd/63 2020-01-04 16:34:27.372004436 -0800
+++ /dev/fd/62 2020-01-04 16:34:27.372004436 -0800
@@ -10,7 +10,7 @@
16 RETURN_VALUE
Disassembly of <code object f at 0xdeadbeef, file "FILENAME", line 1>:
- 2 0 LOAD_NAME 0 (int)
+ 2 0 LOAD_GLOBAL 0 (int)
2 LOAD_CONST 1 (('arg',))
4 BUILD_CONST_KEY_MAP 1
6 LOAD_CONST 2 (<code object g at 0xdeadbeef, file "FILENAME", line 2>)
编辑:这里有一个解决这个问题的拉取请求(如果我对时间的猜测是正确的,应该会出现在 3.8.2 和 3.9.0a3 中):https://github.com/python/cpython/pull/17826
有一些测试代码:
some_type = int
def func0():
def func1(arg: some_type, /):
pass
func0()
我收到以下错误:
Traceback (most recent call last):
...
SystemError: no locals when loading 'some_type'
但是下面的代码按预期工作:
some_type = int
def func0():
def func1(arg: some_type):
pass
func0()
这个也是有效的:
some_type = int
exec('''
def func1(arg: some_type, /):
pass
''')
我知道在未来的版本中将不再在定义时评估注释;也可以在 3.7+ 版本中激活此类行为。像
from __future__ import annotations
some_type = int
def func0():
def func1(arg: some_type, /):
pass
func0()
也没有问题。但是,问题是关于函数定义时当前的奇怪行为。 some_type
绝不是 func0
的局部变量,尽管 python 这么认为。又一精良版:
def func0():
some_type = int
def func1(arg: some_type, /):
pass
func0()
我读过 PEP 570 但没有找到任何关于注解声明的内容。
我的python版本:
sys.version_info(major=3, minor=8, micro=0, releaselevel='final', serial=0)
这是 cpython 中的一个错误——我已经在这里打开了一个问题:https://bugs.python.org/issue39215
查看这两个函数的反汇编,它似乎在构建注释类型时错误地使用了 LOAD_NAME
而不是 LOAD_GLOBAL
-- 这是仅具有和不具有位置的区别参数:
$ diff -u <(python3.9 -m dis t2.py | sed 's/0x[a-f0-9]*/0xdeadbeef/g;s/t2\.py/FILENAME/g') <(python3.9 -m dis t3.py | sed 's/0x[a-f0-9]*/0xdeadbeef/g;s/t3\.py/FILENAME/g')
--- /dev/fd/63 2020-01-04 16:34:27.372004436 -0800
+++ /dev/fd/62 2020-01-04 16:34:27.372004436 -0800
@@ -10,7 +10,7 @@
16 RETURN_VALUE
Disassembly of <code object f at 0xdeadbeef, file "FILENAME", line 1>:
- 2 0 LOAD_NAME 0 (int)
+ 2 0 LOAD_GLOBAL 0 (int)
2 LOAD_CONST 1 (('arg',))
4 BUILD_CONST_KEY_MAP 1
6 LOAD_CONST 2 (<code object g at 0xdeadbeef, file "FILENAME", line 2>)
编辑:这里有一个解决这个问题的拉取请求(如果我对时间的猜测是正确的,应该会出现在 3.8.2 和 3.9.0a3 中):https://github.com/python/cpython/pull/17826