как определить эту строку кода в python, чтобы пройти проверку mypy

#python #python-3.x #mypy #python-typing

#питон #python-3.x #mypy #python-типизация

Вопрос:

У меня есть такое определение в моем коде python:

 options = defaultdict(lambda: defaultdict(lambda: defaultdict(str)))
options['modem1']['ByCost'] = ...
options['modem1']['ByCarrier'] = ...
options['modem1']['BySimSignal'] = ...
options['modem1']['SwitchBackByTimer'] = ...
 

И это завершается неудачей во время моей предварительной проверки / mypy для сообщения о том, что :

 Need type annotation for 'options'
 

Поскольку я не вижу ничего плохого в этом коде, есть ли какие-либо обходные пути, с помощью которых я мог бы передать проверку mypy для этой строки?

Кстати, я ищу альтернативные способы, кроме настройки этого в моем коде :

 disable_error_codes with error code var-annotated
 

Большое спасибо!

Джек

Ответ №1:

На Python 3.9 , благодаря PEP 585, вы можете использовать defaultdict себя для аннотаций типов, делая это простым, хотя и несколько избыточным / подробным (см. Внизу Ответа для решения только для 3.9 , которое немного менее избыточно / подробно, но не может быть так же легко перенесено на 3.8 и более ранние версии):

 from collections import defaultdict

options: defaultdict[str, defaultdict[str, defaultdict[str, str]]] = defaultdict(lambda: defaultdict(lambda: defaultdict(str)))
 

Обратите внимание, что это предполагает, что у вас на самом деле есть три уровня defaultdict ; ваш код опускается только на два уровня, поэтому вы получите ошибку проверки, если вы это сделаете:

 options['modem1']['ByCost'] = 'abc'
 

потому что вам действительно нужен был еще один уровень str ключей:

 options['modem1']['ByCost']['xyz'] = 'abc'
 

Если вам действительно нужны два слоя defaultdict , обрежьте его обратно до просто:

 options: defaultdict[str, defaultdict[str,str]] = defaultdict(lambda: defaultdict(str))

options['modem1']['ByCost'] = 'abc'
 

Если вы используете Python 3.8 или более раннюю версию, замените аннотацию using defaultdict на typing.DefaultDict аннотацию, сделав ее:

 from collections import defaultdict
from typing import DefaultDict

options: DefaultDict[str, DefaultDict[str, DefaultDict[str, str]]] = defaultdict(lambda: defaultdict(lambda: defaultdict(str)))
# Or if only two levels:
options: DefaultDict[str, DefaultDict[str, str]] = defaultdict(lambda: defaultdict(str))
 

Менее избыточное решение

Примечание: Использование 3.9 позволяет вам как аннотировать, так и использовать аннотированный тип, поэтому в качестве решения только для 3.9 вы могли бы сделать (для простоты показан двухслойный случай):

 options = defaultdict[str, defaultdict[str,str]](lambda: defaultdict(str))
 

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

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

1. Спасибо за советы. Это решает мою проблему.

2. Просто хочу еще раз сказать вам спасибо. Вы сэкономили мне уйму времени, чтобы решить эту проблему. Большое спасибо.