Подсказки типа переменной не проверяются внутри функции

#python #type-hinting

Вопрос:

Когда вы выполняете этот код:

 from typing import Dict

bar: Dict[int, int, int] = dict()
 

возникает исключение TypeError с сообщением Too many parameters for typing.Dict; actual 3, expected 2 . Но когда вы определяете переменную внутри функции:

 from typing import Dict

def foo():
    bar: Dict[int, int, int] = dict()

foo()
 

на этот раз не возникает никаких исключений. Это ожидаемое поведение или ошибка?

Ответ №1:

Это предполагаемое поведение и определено в PEP 526 — Синтаксис для аннотаций переменных #Эффекты выполнения аннотаций типов.

Аннотирование локальной переменной приведет к тому, что интерпретатор будет рассматривать ее как локальную, даже если она никогда не была назначена. Аннотации для локальных переменных оцениваться не будут:

 def f():
    x: NonexistentName  # No error.
 

Однако, если он находится на уровне модуля или класса, то тип будет оценен:

 x: NonexistentName  # Error!
class X:
    var: NonexistentName  # Error!
 

Кроме того, PEP 563 — Отложенная оценка аннотаций определяет, что использование from __future__ import annotations с python 3.7 предотвращает оценку этих аннотаций.

В этом ОПТОСОЗ предлагается изменить аннотации функций и аннотации переменных, чтобы они больше не оценивались во время определения функции. Вместо этого они сохраняются в __аннотациях__ в строковой форме.

 from __future__ import annotations
from typing import Dict

bar: Dict[int, int, int] = dict()  # no errors
 

Комментарии:

1. Что касается того, почему локальные аннотации не оцениваются, помните, что сама аннотация может быть произвольным кодом, а не просто подсказкой типа (хотя использование подсказок, не связанных с типом, не рекомендуется). Таким образом, было бы исключением оценивать аннотацию в определении функции, когда никакой другой код внутри функции не оценивается. PEP 563 делает это спорным вопросом, указывая, что аннотации не будут оцениваться ни при определении, ни во время вызова: аннотации становятся неявными str литералами, которые будут оцениваться только в том случае, если вы сделаете это явно.