理解Python类型注释在索引之后

huangapple go评论87阅读模式
英文:

Understanding Python type annotation after indexing

问题

我在我的代码中犯了一个错字,将一个=替换成了一个:,导致一行代码看起来像这样:

data = {}
data["teapot"]: "turtle"

令我吃惊的是,这没有产生语法错误,但我不明白它在做什么。

然后,我转储了抽象语法树,似乎它是一种类型提示,尽管我没有在其他地方找到类似的示例:

>>> import ast
>>> print(ast.dump(ast.parse("data['x']: 'turtle'"), indent=2))
Module(
  body=[
    AnnAssign(
      target=Subscript(
        value=Name(id='data', ctx=Load()),
        slice=Constant(value='x'),
        ctx=Store()),
      annotation=Constant(value='turtle'),
      simple=0)],
  type_ignores=[])

这段代码是什么意思?如果根据抽象语法树的分析,它是一种类型提示,那么它是否有实际用途?

英文:

I made a typo in my code and replaced an = with a :, which resulted in a line of code that looked like:

data = {}
data["teapot"]: "turtle"

To my surprise, this did not produce a syntax error, but I don't understand what it's doing.

I then dumped the abstract syntax tree and it appears that it is some sort of type hint, although not one I've been able to find an example of elsewhere:

>>> import ast
>>> print(ast.dump(ast.parse("data['x']: 'turtle'"), indent=2))
Module(
  body=[
    AnnAssign(
      target=Subscript(
        value=Name(id='data', ctx=Load()),
        slice=Constant(value='x'),
        ctx=Store()),
      annotation=Constant(value='turtle'),
      simple=0)],
  type_ignores=[])

What does this code mean? If it is, as I guess based on the AST, a type hint, does it have any practical use?

答案1

得分: 2

这是来自类型注解语法的两个特性的组合。

首先,你可以在任何可能语法上可以成为赋值目标的表达式后面放置类型提示。这包括标识符(例如 data ),索引表达式(例如 data["teapot"] ),属性(例如 data.teapot )。它不必是实际的赋值;通常在函数或类的开头放置变量的类型提示,稍后再填充值。

其次,类型名称可以是字符串文字,因为这用于对尚未定义的类型进行前向引用。前向引用在你有类型提示的循环或递归链时是必需的,以解决鸡和蛋的问题。

所以你的示例符合这种情况

data["teapot"]: "turtle"

它只是声明 data["teapot"] 的最终值将是名为 turtle 的类型,该类型可能尚未定义。

英文:

This comes from a combination of two features of type annotation syntax.

First, you can put a type hint after any expression that could syntactically be the target of an assignment. This includes identifiers (e.g. data), indexed expressions (e.g. data["teapot"]), attributes (e.g. data.teapot). It doesn't have to be an actual assignment; it's common to put type hints for variables at the beginning of a function or class, and fill in the value later.

Second, the type name can be a string literal, because this is used for forward references to types that haven't yet been defined. Forward references are needed when you have circular or recursive chains of type hints, to solve the chicken-and-egg problem.

So your example fits this case

data["teapot"]: "turtle"

It simply declares that the eventual value of data["teapot"] will be of the type named turtle, which may not yet be defined.

答案2

得分: 0

在Python中,类型提示 是一种以静态类型的方式编写Python代码的方式。它通常对运行时几乎没有影响(从技术上讲仍在使用,但很少见)。更常见的情况是,您会与静态类型检查工具一起使用,如mypy、pylint或PyCharm IDE。

在代码中使用引号是进行前向声明的一种方式。另请参阅:https://stackoverflow.com/questions/46458470/should-you-put-quotes-around-type-annotations-in-python

您的代码片段类似于这里的代码:https://stackoverflow.com/questions/74308012/type-hints-without-value-assignment-in-python。但是,它似乎并没有实际添加任何注释:

a: int = 1
b: float
c = {}
c['foo']: str

print(__annotations__)
# 结果是
# {'a': <class 'int'>, 'b': <class 'float'>}

至于实际用途,Pylint在检查时会引发错误,所以这可能不是标准语法。有趣的是,像 1+2+3: intf(x): float 这样的表达式会在运行时引发 SyntaxError: illegal target for annotation 错误,但在这种情况下不会。我猜测一些静态类型检查工具可以使用这种语法来注释数组和字典中的单个元素。

英文:

Type hint in python is a way to write python in a statically typed manner. It generally has little effect on the runtime (technically still used but rare). More often, you use it with a static type checker like mypy, pylint or PyCharm IDE.

Using quote is doing forward declaration. See also: https://stackoverflow.com/questions/46458470/should-you-put-quotes-around-type-annotations-in-python

Your code snippet is similar to the one here: https://stackoverflow.com/questions/74308012/type-hints-without-value-assignment-in-python. However, it does not seem to actually add any annotations:

a: int = 1
b: float
c = {}
c[&#39;foo&#39;]: str

print(__annotations__)
# results in
# {&#39;a&#39;: &lt;class &#39;int&#39;&gt;, &#39;b&#39;: &lt;class &#39;float&#39;&gt;}

As for practical use, Pylint throws an error when checking, so this is probably not a standard syntax. Interstingly, expressions like 1+2+3: int or f(x): float results in SyntaxError: illegal target for annotation at runtime, but not in this case. I'm guessing it's possible for some static type checker to use this syntax to annotate individual elements in arrays and dictionaries.

huangapple
  • 本文由 发表于 2023年7月11日 12:35:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76658739.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定