这种奇怪的冒号行为在做什么?

jus*_*gel 97 python python-3.x

我使用的是Python 3.6.1,我遇到了一些非常奇怪的东西.我有一个简单的字典分配拼写错误,花了我很长时间才找到.

context = {}
context["a"]: 2
print(context)
Run Code Online (Sandbox Code Playgroud)

产量

{}
Run Code Online (Sandbox Code Playgroud)

代码context["a"]: 2在做什么?它不会引起SyntaxError它应该IMO的时间.起初我以为它创造了一个切片.然而,打字repr(context["a"]: 2)提出了一个SyntaxError.我也输入context["a"]: 2了控制台,控制台没有打印任何东西.我想也许它回来了None,但我不太确定.

我也认为它可能是一行if语句,但这也不应该是正确的语法.

另外,context["a"]应该提高一个KeyError.

我很困惑.到底是怎么回事?

vau*_*tah 92

您不小心编写了语法正确的变量注释.该功能是在Python 3.6中引入的(参见PEP 526).

虽然变量注释被解析为带注释的赋值的一部分,但赋值语句是可选的:

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]
Run Code Online (Sandbox Code Playgroud)

因此,在 context["a"]: 2

  • context["a"] 是注释目标
  • 2 是注释本身
  • context["a"] 没有初始化

PEP声明"注释的目标可以是任何有效的单一分配目标,至少在语法上(由类型检查器决定如何处理)",这意味着密钥不需要存在注释(因此没有KeyError).这是原始PEP的一个例子:

d = {}
d['a']: int = 0  # Annotates d['a'] with int.
d['b']: int      # Annotates d['b'] with int.
Run Code Online (Sandbox Code Playgroud)

通常,注释表达式应该评估为Python类型 - 在注释的所有主要用途都是类型提示之后,但它没有强制执行.无论结果的类型或值如何,注释都可以是任何有效的 Python表达式.

正如您所看到的,此时类型提示非常宽松且很少有用,除非您有一个静态类型检查器,如mypy.

  • 这不应该需要`=`赋值运算符吗?密钥不存在.这对我来说感觉不对. (11认同)
  • 奇怪的是它会允许你注释一个尚未定义的目标.如果我的第一行是`x:str`并且紧接着是`type(x)`,那么解释器将引发一个`NameError`.IMO语法应该强制对象是预定义的,或者是在现场定义的.这只是引入了混乱. (6认同)
  • @Idlehands 允许此语法可能使您能够在函数定义中使用类型提示。在“def f(x: str): ...”中,“x”在注释时也没有定义。 (3认同)
  • @Idlehands虽然这打败了目的.在`x:str`之前使`x ='我是一个字符串'`会使后者变得多余..这根本就不应该添加.评论很好; 我从来没有用它的方式表现出来. (2认同)