Я работаю над базами кода с подробными подсказками по типам, проверенными mypy. В нескольких случаях у нас есть отображение из enum.Enum или другого небольшого конечного набора статически известных значений (
# 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) .
Я работаю над базами кода с подробными подсказками по типам, проверенными mypy. В нескольких случаях у нас есть отображение из enum.Enum или другого небольшого конечного набора статически известных значений ([code]typing.Literal[/code]) к фиксированным значениям, поэтому использование словаря удобно: [code]# GOOD from enum import Enum, auto
print(lookup[Foo.X]) [/code] Однако этот словарь не обязательно должен быть исчерпывающим (то есть полным): mypy вполне устраивает отсутствие ключей, а индексирование с отсутствующим ключом завершится ошибкой во время выполнения. На практике это может легко произойти с большим перечислением (забывание члена при определении dict) или при добавлении члена в существующее перечисление (особенно, если поиск представляет собой совершенно другой файл).< /p> Например, это отлично передает mypy --strict, но не выполняется во время выполнения, потому что мы «забыли» обновить сам поиск: [code]# BAD from enum import Enum, auto
class Foo(Enum): X = auto() Y = auto() Z = auto() # NEW
print(lookup[Foo.Z]) # CHANGED [/code] Мне бы хотелось иметь возможность помечать определенные словари/отображения как полные/исчерпывающие, то есть, например, mypy выдаст ошибку об определении поиска в ПЛОХОЙ пример выше. [list] [*]Можно ли его аннотировать текущими подсказками типов Python как общий тип для любого Enum или Literal[ ...] тип ключа? (Например, синтаксис в лучшем случае, на который мы надеемся: поиск: ExhaustiveDict[Foo, str] = {... или поиск: ExhaustiveDict[Literal[1, 2], str] = {1: "a", 2: "b".) [*]Если нет, можно ли это сделать для конкретной пары типов ключ/значение? (Например, разумным синтаксисом может быть поиск: ExhaustiveDictFooTo[str] = {...} и/или поиск: ExhaustiveDictFooToStr = {...}, если определение этих типов разумно.) [/list] Я рад изменить точный синтаксис, с помощью которого мы создаем словарь, но тем ближе он к {Foo.X: " круто", Foo.Y: "что угодно", тем лучше.
Дополнительные примечания для справки/чтобы было ясно, что мы понимаем: [list] [*]В настоящее время мы используем обходной путь исчерпывающих операторов if, но переход от компактного dict к компактному раздражает. вся функция: [code]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) [/code] Если Foo позже будет изменен на включение Z, мы получим ошибку в последней строке, например, аргумент 1 «исчерпывающий» имеет несовместимый тип «Literal[Foo.Z]» "; ожидалось "NoReturn", что означает, что мы не обработали этот случай ранее в if (сообщение не сразу очевидно, но в конечном итоге оно просто соответствует шаблону того, что оно означает, и намного лучше, чем ничего). (Предположительно, здесь также можно использовать match/[code]case[/code], но мы все еще используем 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) . [/list]
Я работаю над базами кода с подробными подсказками по типам, проверенными mypy. В нескольких случаях у нас есть отображение из enum.Enum или другого небольшого конечного набора статически известных значений ( typing.Literal ) к фиксированным...
Я пытаюсь создать функцию, которая проходит через Union и Literal и извлекает их возможные значения. Я пытаюсь сделать это, потому что хочу создать функцию, которая принимает функцию и описывает параметры этой переданной функции в формате json-схемы...
Предположим, у меня есть функция, которая возвращает словарь, имеющий целые числа в качестве ключей и экземпляры определенного пользовательского класса в качестве значений:
при вводе import Dict класс А: а = 4 защита my_f() -> dict: вернуть {0:...
Можно ли передать значения TypedDict как общие значения внутри класса, чтобы включить подсказку типа?
У меня есть словарь, в котором я хотел бы иметь возможность получите аннотации типов из переданного общего TypeDict внутри __getattr__.
В этом...
Можно ли передать значения TypedDict как общие значения внутри класса, чтобы включить подсказку типа?
У меня есть словарь, в котором я хотел бы иметь возможность получите аннотации типов из переданного общего TypeDict внутри __getattr__.
В этом...