mypy set словарные ключи / интерфейс - PullRequest
0 голосов
/ 01 июня 2018

Предположим, у меня есть функция, которая принимает словарь в качестве параметра:

def f(d: dict) -> None:
    x = d["x"]
    print(x)

Можно ли указать, что этот словарь должен иметь ключ "x" для mypy?Я ищу что-то похожее на интерфейс из машинописи , не меняя d на класс.

Причина, по которой я не хочу менять d на класс, заключается в том, чтопотому что я изменяю большую существующую кодовую базу, чтобы добавить проверку типа mypy, и этот словарь используется во многих местах.Мне пришлось бы изменить много кода, если бы мне пришлось изменить все экземпляры d["x"] на d.x.

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Mypy расширяет PEP 484, предоставляя тип TypedDict.Это позволяет указывать конкретные атрибуты типа dict.В вашем случае вы можете сделать следующее:

from mypy_extensions import TypedDict

# you can also do HasX = TypedDict('HasX', {'x': str})
class HasX(TypedDict):
    x: str

def f(x: HasX) -> None:
    reveal_type(d["x"])  # error: Revealed type is 'builtins.str'
0 голосов
/ 01 июня 2018

Нет, с помощью typing (PEP 484 и PEP 526) вы не можете объявить, что в контейнере должен присутствовать определенный ключ.Все, что вы можете объявить - это types , а не содержимое среды выполнения.'x' - это конкретное строковое значение , а не тип.

Я знаю, что вы конкретно не хотите этого делать, но, возможно, ответ - рассмотреть другую структуру данных, такую ​​как именованный кортеж или класс данных, где вы можете указать атрибут, который имеет тип.

Вот что действительно делает объявление машинописного текста:

Функция printLabel имеет единственный параметр, который требует, чтобы переданный объект имел свойство label типа string.

Атрибуты Python являются моральным эквивалентом свойств объекта Typescript.То, что нотация объектов Typescript и словари Python имеют много общего, возможно, сбивает с толку вопросы, но вы не должны рассматривать объявления объектов Typescript как что-либо, кроме классов, когда пытаетесь отобразить концепции на Python.

mypy действительно включает расширениядо typing, которые выходят за пределы стандарта хинтинга типа Python.Это включает в себя mypy_extensions.TypeDict объект , который работает так же, как объявление typing.TypeVar :

from mypy_extensions import TypedDict

SomeDict = TypeDict('SomeDict', {'x': str})

def f(d: SomeDict) -> None:
    x = d['x']
    print(x)

или использование синтаксиса на основе классов:

class SomeDict(TypeDict)
    x: str

Ключи в объявлении TypeDict являются либо обязательными, либо необязательными (если вы указали total=False в объявлении);вам придется использовать наследование, чтобы создать тип с некоторыми необязательными ключами, см. документацию по ссылке.

Но учтите, что TypeDict является экспериментальным и может быть отброшен снова или радикально изменен в будущем выпуске Mypy и недоступен в других средствах проверки подсказок типов Python.

...