Вопрос-Ответ

What are variable annotations?

Что такое аннотации переменных?

Скоро выйдет Python 3.6. PEP 494 -- В расписании выпуска Python 3.6 упоминается конец декабря, поэтому я просмотрел Что нового в Python 3.6, чтобы увидеть, что в них упоминаются аннотации переменных:


ВPEP 484 введен стандарт для аннотаций типов параметров функций, также известных как подсказки по типу. Этот PEP добавляет в Python синтаксис для аннотирования типов переменных, включая переменные класса и переменные экземпляра:


primes: List[int] = []

captain: str # Note: no initial value!

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

Так же, как и для аннотаций функций, интерпретатор Python не придает аннотациям переменных никакого особого значения и только сохраняет их в специальном атрибуте __annotations__ класса или модуля. В отличие от объявлений переменных в языках со статической типизацией, целью синтаксиса аннотаций является предоставление простого способа указания метаданных структурированного типа для инструментов и библиотек сторонних производителей с помощью абстрактного синтаксического дерева и __annotations__ атрибута.


Итак, из того, что я прочитал, они являются частью подсказок типа, поступающих из Python 3.5, описанных в Что такое подсказки типа в Python 3.5.

Я следую примеру captain: str и class Starship, но не уверен в последнем: как это primes: List[int] = [] объясняет? Определяет ли он пустой список, который допускает только целые числа?

Переведено автоматически
Ответ 1

Что такое аннотации переменных?


Аннотации переменных - это всего лишь следующий шаг после # type комментариев, как они были определены в PEP 484; обоснование этого изменения приведено в соответствующем разделе PEP 526.

Итак, вместо указания типа с помощью:

primes = []  # type: List[int]

Был введен новый синтаксис, позволяющий напрямую аннотировать тип с присвоением формы:

primes: List[int] = []

который, как указал @Martijn , обозначает список целых чисел, используя типы, доступные в typing и инициализируя его пустым списком.


Какие изменения это приносит?


Первым внесенным изменением был новый синтаксис, который позволяет вам аннотировать имя типом, либо отдельно после : символа, либо необязательно аннотировать, одновременно присваивая ему значение:

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 потому что 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]}, {})

Где a ChainMap используется для получения аннотаций для данного класса (расположенных в первом отображении) и всех аннотаций, определенных в базовых классах, найденных в нем mro (последующие сопоставления, {} для object).

Наряду с новым синтаксисом был добавлен новый ClassVar тип для обозначения переменных класса. Да, stats в вашем примере на самом деле это переменная экземпляра, а не a ClassVar.


Буду ли я вынужден это использовать?


Как и в случае с подсказками по типам из PEP 484, они полностью необязательны и в основном используются для инструментов проверки типов (и всего остального, что вы можете создать на основе этой информации). Это будет предварительно, когда выйдет стабильная версия Python 3.6, поэтому в будущем могут быть добавлены небольшие изменения.

Ответ 2

Все, что находится между : и =, является подсказкой типа, поэтому primes действительно определяется как List[int], и изначально устанавливается в пустой список (и stats изначально является пустым словарем, определенным как Dict[str, int]).

List[int] и Dict[str, int] не являются частью следующего синтаксиса, однако они уже были определены в Python 3.5 typing hints PEP. В 3.6 PEP 526 – Синтаксис для аннотаций к переменным предложение только определяет синтаксис для прикрепления одних и тех же подсказок к переменным; раньше вы могли прикреплять подсказки типа только к переменным с комментариями (например, primes = [] # List[int]).

Оба List и Dict являются универсальными типами, указывающими на то, что у вас есть список или сопоставление словаря с конкретным содержимым.

Для List существует только один "аргумент" (элементы в [...] синтаксисе), тип каждого элемента в списке. Для Dict первым аргументом является тип ключа, а вторым - тип значения. Итак, все значения в primes списке являются целыми числами, а все пары ключ-значение в stats словаре являются (str, int) парами, преобразующими строки в целые числа.

Смотрите typing.List и typing.Dict определения, раздел о обобщениях, а также PEP 483 – Теория подсказок по типам.

Как и подсказки типа в функциях, их использование необязательно и также считается аннотациями (при условии, что есть объект, к которому их можно прикрепить, то есть глобальные значения в модулях и атрибуты в классах, но не локальные значения в функциях), которые вы могли бы проанализировать с помощью __annotations__ атрибута. Вы можете прикреплять произвольную информацию к этим аннотациям, вы не ограничены строго информацией подсказки типа.

Возможно, вы захотите прочитать полное предложение; оно содержит некоторые дополнительные функциональные возможности помимо нового синтаксиса; оно определяет, когда такие аннотации оцениваются, как их анализировать и как объявить что-либо, например, как атрибут класса или атрибут экземпляра.

python python-3.x