Що таке анотації змінних?


84

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] = []пояснити? Це визначення порожнього списку, який дозволить лише цілі числа?


10
Підказки типу не проводять жодної перевірки типу. primes: List[int] = []- це просто порожній список як primes = []. Різниця полягає в тому, що ви заявляєте, що primes має містити лише ints та сторонні програми, можливо, введіть перевірити вашу програму, щоб перевірити цю претензію, але коли ви запускаєте код у будь-якому інтерпретаторі python, який точно такий же, як написання primes = [], і, отже, primes: List[int] = []; primes.append("string")це все ще відбувається дійсний.
Бакуріу

2
@Bakuriu так, хороший момент. Як описує Джим Фасаракіс-Хілліард у своїй відповіді на Що таке підказки типу в Python 3.5 , чому підказки типуДопомагає перевіряти типи, допомагає в документації та допомагає розробникам розробляти більш точні та надійні інструменти . Взяті з PEP 526 - Синтаксис змінних анотацій , Python залишатиметься мовою, що динамічно набирається, і автори не бажають коли-небудь робити підказки про типи обов’язковими, навіть за домовленістю .
Fedorqui 'SO prestani шкодити'

1
Це відповідає на ваше запитання? Що таке підказки щодо типу в Python 3.5?
AMC

Відповіді:


48

Все між :і =є підказкою типу, тому 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__атрибут. Ви можете додати до цих анотацій довільну інформацію, інформація про підказки типу не обмежується.

Можливо, ви захочете прочитати повну пропозицію ; він містить деяку додаткову функціональність, що перевищує новий синтаксис; він вказує, коли такі анотації оцінюються, як їх самоаналізувати і як оголосити щось як атрибут класу проти атрибута екземпляра, наприклад.


1
Чи можу я розглядати підказки типу як своєрідні "машиночитані" коментарі, оскільки вони не впливають на те, як працює код (крім obj.__annotations__атрибута)?
iBug

2
@iBug: анотації - це машиночитані коментарі, оскільки коментарі в будь-якому випадку читаються людиною. :-)
Мартін Пітерс

59

Що таке анотації змінних?

Анотації змінних - це лише наступний крок до # 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 - Анотації функцій ), до якого додаються метадані типу:

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, тому в майбутньому можуть бути додані невеликі налаштування.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.