Готовится к выпуску 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] = []
объяснить? Это определение пустого списка, который разрешает только целые числа?
источник
primes: List[int] = []
это просто пустой список какprimes = []
. Разница в том, что вы утверждаете, чтоprimes
оно предназначено для содержания толькоint
s, и сторонние приложения могут ввести проверку вашей программы, чтобы проверить это утверждение, но когда вы запускаете код в любом интерпретаторе python, который точно такой же, как и записьprimes = []
, и, таким образом, выполнениеprimes: List[int] = []; primes.append("string")
по-прежнему действительный.Ответы:
Все,
:
что=
находится между и является подсказкой типа, поэтомуprimes
действительно определено какList[int]
, и изначально установлено в пустой список (иstats
изначально является пустым словарем, определенным какDict[str, int]
).List[int]
иDict[str, int]
не являются частью следующего синтаксиса, однако они уже были определены в подсказках ввода Python 3.5 PEP. 3,6 PEP 526 - Синтаксис для переменных аннотаций предложения только определяет синтаксис присоединять те же намеки на переменные; раньше вы могли только присоединять подсказки типа к переменным с комментариями (напримерprimes = [] # List[int]
).Оба
List
иDict
являются универсальными типами, что указывает на то, что у вас есть отображение списка или словаря с определенным (конкретным) содержимым.Для
List
существует только один «аргумент» (элементы в[...]
синтаксисе), тип каждого элемента в списке. ВедьDict
первый аргумент - это тип ключа, а второй - тип значения. Таким образом, все значения вprimes
списке являются целыми числами, а все пары ключ-значение вstats
словаре являются(str, int)
парами, отображающими строки в целые числа.Смотрите
typing.List
иtyping.Dict
определения, в раздел дженериков , а также PEP 483 - Теория типа подсказки .Как и подсказки типов для функций, их использование не является обязательным и также считается аннотациями (при условии, что есть объект для их присоединения, поэтому глобальные объекты в модулях и атрибуты в классах, но не локальные объекты в функциях), которые вы могли бы исследовать через
__annotations__
атрибут. Вы можете прикреплять произвольную информацию к этим аннотациям, вы не ограничены только типом подсказки.Вы можете прочитать полное предложение ; он содержит некоторые дополнительные функции помимо нового синтаксиса; он определяет, когда такие аннотации оцениваются, как их анализировать и как, например, объявить что-то как атрибут класса или как атрибут экземпляра.
источник
obj.__annotations__
атрибута)?Аннотации переменных - это всего лишь следующий шаг после
# 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
(последующих сопоставлениях{}
для объекта).Наряду с новым синтаксисом
ClassVar
был добавлен новый тип для обозначения переменных класса. Ага,stats
в вашем примере это фактически переменная экземпляра , а не файлClassVar
.Как и подсказки типа из
PEP 484
, они полностью необязательны и в основном используются для инструментов проверки типов (и всего, что вы можете создать на основе этой информации). Он будет временным, когда выйдет стабильная версия Python 3.6, поэтому в будущем могут быть добавлены небольшие изменения.источник