1

有一些测试代码:

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)
4

1 回答 1

2

这是 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

于 2020-01-05T00:34:57.680 回答