Python 变量类型批注名称错误不一致

Python 变量类型批注名称错误不一致,python,python-3.x,annotations,python-3.6,Python,Python 3.x,Annotations,Python 3.6,在Python3.6中,该语言引入了新的 但是,当类型不存在时,可能会发生两种不同的情况: >>> def test(): ... a: something = 0 ... >>> test() >>> >>> a: something = 0 Traceback (most recent call last): File "<stdin>", line 1, in <module>

在Python3.6中,该语言引入了新的

但是,当类型不存在时,可能会发生两种不同的情况:

>>> def test():
...     a: something = 0
... 
>>> test()
>>> 
>>> a: something = 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'something' is not defined
>>def test():
...     a:某物=0
... 
>>>测试()
>>> 
>>>a:某物=0
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
NameError:未定义名称“某物”
为什么不存在的类型处理行为不同?它是否会导致人们忽略函数中未定义的类型


注释

使用Python3.6RC1和RC2进行了尝试-行为相同


PyCharm在函数内部和外部突出显示
某些内容作为“未解析引用”。

您可以转到并下载RC2版本以测试注释,但wim所说的已发布版本尚未发布。但是,我确实下载并使用Python3.6解释器尝试了您的代码,没有出现错误。

局部变量(即函数内部)的行为至少在以下部分中有记录:

注释局部变量将导致解释器将其视为局部变量,即使它从未被赋值。将不计算局部变量的注释:

接着解释了全局变量的差异:

但是,如果处于模块或类级别,则将对类型进行评估:

这种行为对我来说似乎很奇怪,因此我只能猜测其原因:如果我们将代码放在一个模块中,那么Python希望存储注释

# typething.py
def test():
    a: something = 0

test()


something = ...

a: something = 0
然后导入它:

>>> import typething
>>> typething.__annotations__
{'a': Ellipsis}
>>> typething.test.__annotations__
{}
为什么有必要将其存储在模块对象上,而不是函数对象上?我还没有一个好的答案。可能是出于性能原因,因为注释是通过静态代码分析生成的,这些名称可能会动态更改:

…本地提供注释的价值并不能抵消每次函数调用时创建和填充注释字典的成本。因此,不会计算和存储函数级别的注释


最直接的答案(补充@wim的答案)来自于讨论提案的地方:

[……]最后是当地人。在这里,我认为我们不应该存储类型——在本地提供注释的价值不足以抵消每次函数调用时创建和填充字典的成本

事实上,我甚至不认为应该在函数执行期间计算类型表达式。例如:

def side_effect():
    print("Hello world")
def foo():
    a: side_effect()
    a = 12
    return a
foo()
不应该打印任何东西。(类型检查器也会抱怨
副作用()
不是有效的类型。)

BDFL本人:-)也没有创建dict,也没有进行评估

目前,函数对象仅存储其定义中提供的注释:

def foo(a: int): 
    b: int = 0

get_type_hints(foo)   # from typing
{'a': <class 'int'>}
def foo(a:int):
b:int=0
从键入中获取_type_提示(foo)#
{'a':}

为局部变量注释创建另一个字典显然被认为成本太高

你可以试着这样写:

>>>a: 'something' = 0

啊,我有Python 3.6.0rc1,让我检查一下Python 3.6.0rc2。谢谢@迪尔默:没有出现错误?这很奇怪。我希望在这两种情况下都会出现错误。无错误“Python 3.6.0rc2(v3.6.0rc2:800a67f7806d,2016年12月16日,14:12:21)”添加了测试函数,并将其称为test()和clean result。@Dilmer很有趣。对于我来说,它在rc2中的行为与在rc1中的行为相同:在函数内部无错误,在函数外部有错误。我在macOS Sierra上试用了Python 3.6.0(v3.6.0:41DF79263A1112016年12月22日,17:23:13)。在函数外部时,它确实会引发错误。也许他们希望避免在函数内部定义一个本地类
C
,然后用
C
在函数中注释变量的问题<代码>C
在其定义执行之前不存在,因此您不能在函数定义时将其存储在
\uuuuuuuuuuuuuuuuuuuuuuuuuuu
属性中。明白了!性能推理是有道理的,我想知道如果在函数中错误地键入变量类型,这是否会导致问题。我想智能编辑器和测试应该会对此有所帮助。谢谢
def foo(a: int): 
    b: int = 0

get_type_hints(foo)   # from typing
{'a': <class 'int'>}
>>>a: 'something' = 0