Python3.6中的变量注释是什么?

2024-05-17 06:31:27 发布

您现在位置:Python中文网/ 问答频道 /正文

Python3.6即将发布。PEP 494 -- Python 3.6 Release Schedule提到12月底,所以我通过What's New in Python 3.6看到他们提到变量注释

PEP 484 introduced standard for type annotations of function parameters, a.k.a. type hints. This PEP adds syntax to Python for annotating the types of variables including class variables and instance variables:

primes: List[int] = []

captain: str  # Note: no initial value!

class Starship:
     stats: Dict[str, int] = {}

Just as for function annotations, the Python interpreter does not attach any particular meaning to variable annotations and only stores them in a special attribute __annotations__ of a class or module. In contrast to variable declarations in statically typed languages, the goal of annotation syntax is to provide an easy way to specify structured type metadata for third party tools and libraries via the abstract syntax tree and the __annotations__ attribute.

因此,根据我所读,它们是来自Python 3.5的类型提示的一部分,在What are Type hints in Python 3.5中描述。

我遵循captain: strclass Starship示例,但不确定最后一个示例:如何解释primes: List[int] = []?它是否定义了一个只允许整数的空列表?


Tags: andofthetoinfortypevariables
2条回答

What are variable annotations?

变量注释只是# type注释的下一步,正如在PEP 484中定义的那样;此更改背后的原理在respective section of PEP 526中突出显示。

所以,不要用以下方式暗示类型:

primes = []  # type: List[int]

引入了新语法以允许使用表单的赋值直接注释类型:

primes: List[int] = []

正如@Martijn所指出的,它通过使用^{}中可用的类型并将其初始化为空列表来表示整数列表。

What changes does it bring?

引入的第一个更改是new syntax,它允许您使用类型注释名称,可以是在:字符之后独立的,也可以是在为名称指定值的同时选择性地进行注释:

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

所以这个例子:

   primes: List[int] = [ ]
#    ^        ^         ^
#  augtarget  |         |
#         expression    |
#                  expression (optionally initialize to empty list)

随着新语法的引入,还引入了其他更改;模块和类现在有一个附加了类型元数据的__annotations__属性(从PEP 3107 -- Function Annotations开始,函数就有了这个属性):

from typing import get_type_hints  # grabs __annotations__

现在__main__.__annotations__保存声明的类型:

>>> from typing import List, get_type_hints
>>> primes: List[int] = []
>>> captain: str
>>> import __main__
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int]}

captain当前不会通过^{}显示,因为get_type_hints只返回也可以在模块上访问的类型;即,它首先需要一个值:

>>> captain = "Picard"
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int], 'captain': <class 'str'>}

使用print(__annotations__)将显示'captain': <class 'str'>,但您确实不应该直接访问__annotations__

同样,对于类:

>>> get_type_hints(Starship)
ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})

其中,ChainMap用于获取给定类(位于第一个映射中)的注释以及在其mro(结果映射,{}中为对象)的基类中定义的所有注释。

除了新语法之外,还添加了一个新的^{}类型来表示类变量。是的,stats在您的示例中实际上是一个实例变量,而不是一个ClassVar

Will I be forced to use it?

与来自PEP 484的类型提示一样,它们是完全可选的,主要用于类型检查工具(以及基于此信息可以生成的任何其他工具)。Python 3.6的稳定版本发布时是临时的,因此将来可能会添加一些小的调整。

:=之间的所有内容都是类型提示,因此primes实际上定义为List[int],并且最初设置为空列表(而stats最初是空字典,定义为Dict[str, int])。

List[int]Dict[str, int]不是下一个语法的一部分,但是这些已经在Python 3.5类型提示PEP中定义。3.6PEP 526 – Syntax for Variable Annotations建议仅定义了将相同提示附加到变量的语法;在您只能将类型提示附加到带有注释的变量(例如primes = [] # List[int])之前。

ListDict都是泛型类型,这表示您有一个具有特定(具体)内容的列表或字典映射。

对于List,只有一个“参数”(在[...]语法中的元素),即列表中每个元素的类型。对于Dict,第一个参数是键类型,第二个参数是值类型。因此,primes列表中的所有值都是整数,stats字典中的所有键值对都是(str, int)对,将字符串映射到整数。

请参见^{}^{}定义、section on Generics以及PEP 483 – The Theory of Type Hints

与函数的类型提示一样,它们的使用是可选的,也被视为注释(前提是有一个对象将它们附加到类中的模块和属性中,因此类中的全局变量,而不是函数中的局部变量),您可以通过__annotations__属性进行内省。您可以将任意信息附加到这些注释中,而不是严格限制为类型提示信息。

您可能需要阅读full proposal;它包含一些新语法之外的附加功能;它指定何时计算此类注释,如何对它们进行内省,以及如何将某些内容声明为类属性与实例属性,例如。

相关问题 更多 >