Введите подсказку для исчерпывающего словаря с ключами Enum/Literal.Python

Программы на Python
Ответить Пред. темаСлед. тема
Гость
 Введите подсказку для исчерпывающего словаря с ключами Enum/Literal.

Сообщение Гость »

Я работаю над базами кода с подробными подсказками по типам, проверенными mypy. В нескольких случаях у нас есть отображение из enum.Enum или другого небольшого конечного набора статически известных значений (

Код: Выделить всё

typing.Literal
) к фиксированным значениям, поэтому использование словаря удобно:

Код: Выделить всё

# GOOD
from enum import Enum, auto

class Foo(Enum):
X = auto()
Y = auto()

lookup: dict[Foo, str] = {Foo.X: "cool", Foo.Y: "whatever"}

print(lookup[Foo.X])
Однако этот словарь не обязательно должен быть исчерпывающим (то есть полным): mypy вполне устраивает отсутствие ключей, а индексирование с отсутствующим ключом завершится ошибкой во время выполнения. На практике это может легко произойти с большим перечислением (забывание члена при определении dict) или при добавлении члена в существующее перечисление (особенно, если поиск представляет собой совершенно другой файл).< /p>
Например, это отлично передает mypy --strict, но не выполняется во время выполнения, потому что мы «забыли» обновить сам поиск:

Код: Выделить всё

# BAD
from enum import Enum, auto

class Foo(Enum):
X = auto()
Y = auto()
Z = auto() # NEW

lookup: dict[Foo, str] = {Foo.X: "cool", Foo.Y: "whatever"}

print(lookup[Foo.Z]) # CHANGED
Мне бы хотелось иметь возможность помечать определенные словари/отображения как полные/исчерпывающие, то есть, например, mypy выдаст ошибку об определении поиска в ПЛОХОЙ пример выше.
  • Можно ли его аннотировать текущими подсказками типов Python как общий тип для любого Enum или Literal[ ...] тип ключа? (Например, синтаксис в лучшем случае, на который мы надеемся: поиск: ExhaustiveDict[Foo, str] = {... или поиск: ExhaustiveDict[Literal[1, 2], str] = {1: "a", 2: "b".)
  • Если нет, можно ли это сделать для конкретной пары типов ключ/значение? (Например, разумным синтаксисом может быть поиск: ExhaustiveDictFooTo[str] = {...} и/или поиск: ExhaustiveDictFooToStr = {...}, если определение этих типов разумно.)
Я рад изменить точный синтаксис, с помощью которого мы создаем словарь, но тем ближе он к {Foo.X: " круто", Foo.Y: "что угодно", тем лучше.

Дополнительные примечания для справки/чтобы было ясно, что мы понимаем:
  • В настоящее время мы используем обходной путь исчерпывающих операторов if, но переход от компактного dict к компактному раздражает. вся функция:

    Код: Выделить всё

    from typing import NoReturn
    def exhaustive(val: NoReturn) -> NoReturn:
    raise NotImplementedError(val)
    
    def lookup(val: Foo) -> str:
    if val is Foo.X:
    return "cool"
    elif val is Foo.Y:
    return "whatever"
    else:
    exhaustive(val)
    
    Если Foo позже будет изменен на включение Z, мы получим ошибку в последней строке, например, аргумент 1 «исчерпывающий» имеет несовместимый тип «Literal[Foo.Z]» "; ожидалось "NoReturn", что означает, что мы не обработали этот случай ранее в if (сообщение не сразу очевидно, но в конечном итоге оно просто соответствует шаблону того, что оно означает, и намного лучше, чем ничего). (Предположительно, здесь также можно использовать match/, но мы все еще используем Python 3.9, а не 3.10.)
  • Это одинаково хорошо применимо и к использованию Literal[1, 2, 3] или Literal[ "foo", "bar", "baz"] в качестве типа ключа в дополнение к enum.Enum.
  • Это несколько перекрывается с набором текста .TypedDict и его значение total=True по умолчанию, но AFAICT ограничено строковыми ключами, записанными буквально в определении TypedDict (поэтому нам нужно будет преобразовать перечисления в строки и иметь дополнительную функциональность который проверяет, что определение TypedDict действительно соответствует перечислению).
  • По сути, я спрашиваю, как написать Python, эквивалентный типу TypeScript Record, что-то вроде Record[ Foo, str] или Record[Literal["foo", "bar"], str] (эквивалент Record в Typescript) .


Подробнее здесь: https://stackoverflow.com/questions/720 ... teral-keys
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Введите подсказку для исчерпывающего словаря с ключами Enum/Literal.
    Anonymous » » в форуме Python
    0 Ответы
    13 Просмотры
    Последнее сообщение Anonymous
  • Введите подсказку объекта, созданного путем ввода.Literal[]
    Anonymous » » в форуме Python
    0 Ответы
    12 Просмотры
    Последнее сообщение Anonymous
  • Введите подсказку словаря Python, имеющего целые числа в качестве ключей.
    Гость » » в форуме Python
    0 Ответы
    39 Просмотры
    Последнее сообщение Гость
  • Введите подсказку для объекта пользовательского словаря как TypedDict.
    Anonymous » » в форуме Python
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • Введите подсказку для объекта пользовательского словаря как TypedDict.
    Anonymous » » в форуме Python
    0 Ответы
    9 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»