#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. Просто хочу еще раз сказать вам спасибо. Вы сэкономили мне уйму времени, чтобы решить эту проблему. Большое спасибо.