Что такое аннотации переменных?
Скоро выйдет 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__
атрибута. Вы можете прикреплять произвольную информацию к этим аннотациям, вы не ограничены строго информацией подсказки типа.
Возможно, вы захотите прочитать полное предложение; оно содержит некоторые дополнительные функциональные возможности помимо нового синтаксиса; оно определяет, когда такие аннотации оцениваются, как их анализировать и как объявить что-либо, например, как атрибут класса или атрибут экземпляра.