Должен ли я привести к строке, а затем к int для mypy?

У меня есть конфигурация, которую я загрузил в dict. Он содержит целое число config["logging"]["backup_count"]. Однако type(config["logging"]["backup_count"]) возвращается object. Итак, когда я собираюсь передать это в следующее:

TimedRotatingFileHandler(log_file, backupCount=config["logging"]["backup_count"], when = "midnight", interval=1)

mypy жалуется, что я пытаюсь поставить object там, где ожидается int. Конечно, это поправимо, добавив приведение типов:

TimedRotatingFileHandler(log_file, backupCount=int(str(config["logging"]["backup_count"])), when = "midnight", interval=1)

но это кажется неуклюжим. Должен ли я это делать?

Я новичок в mypy и пишу на Python. Я хотел бы знать правильный протокол для решения подобных проблем. В частности, следует ли мне выполнять приведение -to-str-to-int или что-то еще?

Обновлено: Должен ли я использовать TypedDict? Если мой словарь считывается, например, из файла .toml, есть ли простой способ создать из него TypedDict с правильным набором текста (я заранее знаю, какие типы конфигурации должны быть)?

Есть ли там ошибка? Я имею в виду, можно ли запустить код Python без завершения с помощью ValueError, TypeError или чего-то еще?

Luke L 06.08.2024 01:09

При запуске скрипта ошибок нет. Только ошибка при вызове mypy в скрипте для проверки типа.

wormram 06.08.2024 01:16

Если это так, то просто игнорируйте это.

Luke L 06.08.2024 01:18

Как config определить? Вероятно, вы захотите определить один или несколько TypedDict, чтобы mypy точно знал, какой тип связан с каждой клавишей.

chepner 06.08.2024 14:25

если type(thing) возвращает object во время выполнения, никакие «приведения» не превратят его в int. Это не C++ или Java, где объект можно «воспринимать» как один из его суперклассов путем приведения - int, будучи подклассом, может «делать все, что делает «объект», но у него есть больше вещей (например, наличие значения) . И type всегда будет возвращать фактический класс экземпляра.

jsbueno 06.08.2024 14:43

@jsbueno Полностью согласен, object - это object, он не может стать int.

Luke L 07.08.2024 02:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
6
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваша проблема связана только с проблемой проверки типов. Если TimedRotatingFileHandler.__init__() может принимать object вместо int, тогда все в порядке. Вероятно, вы можете просто игнорировать проблемы проверки типов. Они предназначены для случаев, когда вызванные методы/функция на самом деле не принимают объект типа object и приводят к TypeError. Если это просто проблема с аннотацией типа, я предлагаю вам либо проигнорировать ее, либо изменить аннотацию на что-то вроде этого (учитывая, что TimedRotatingFileHandler — это ваш собственный класс и, следовательно, вы можете его изменить):

def __init__(self, logfile: File, backupCount: int|object, *args, **kwargs):
    # code here

Вы правы, у меня нет времени заниматься проверкой типов в моем словаре. TimedRotatingFileHandler — не мой класс, и он отказывается принимать object вместо int вместо backupCount. Я понял, что это можно исправить с помощью TypedDict, но накладные расходы на эту работу кажутся невероятными.

wormram 06.08.2024 01:41

Это устраняет неправильную проблему. TimedRotatingFileHandler конкретно, что ему нужен int. Вместо того, чтобы ослаблять это ограничение, вам следует убедиться, что mypy знает точный тип config.

chepner 06.08.2024 14:25

@chepner Интересно, TimedRotatingFileHandler — это библиотечный класс? Если это не собственный класс пользователя, то ваш ответ лучше моего. Однако, если это собственный класс OP, то лучше либо игнорировать проблему проверки типов, либо изменить аннотацию типа в определении класса, как указано в моем сообщении. Кроме того, я считаю, что аннотации типов только создают ненужный шум и проблемы, которые отвлекают программистов от реальных проблем, а не приносят никакой пользы. Это только мое мнение, конечно.

Luke L 07.08.2024 02:35

@wormram Можете ли вы сказать мне, что не так с моим ответом, который заслуживает того, чтобы его не приняли? Разве вы не говорили в предыдущем комментарии, что использование TypedDict создает накладные расходы, а также что у вас нет на это времени?

Luke L 07.08.2024 03:25
Ответ принят как подходящий

Вам следует определить TypedDict, которые точно определяют тип config["logging"]["backup_count"]. Минимальная демонстрация:

from typing import TypedDict


class LoggingConfig(TypedDict):
    backup_count: int

class Config(TypedDict):
    logging: LoggingConfig


config: Config = {"logging": {"backup_count": 3}}

reveal_type(config["logging"]["backup_count"])  # int

Более быстрый обходной путь: если вы уверены, что config["logging"]["backup_cont"] действительно является int, просто скажите mypy:

from typing import cast

TimedRotatingFileHandler(log_file, backupCount=cast(int, config["logging"]["backup_count"]), when = "midnight", interval=1)

(По-прежнему существуют накладные расходы на вызов cast, но во время выполнения все, что он делает, — это возвращает второй аргумент, а не фактически создает новое значение int. При проверке типа mypy предполагает, что второй аргумент имеет тип, указанный первый.)

Я думаю, что ваш ответ просто слишком усложняет ситуацию. MyPy — это просто средство проверки типов, а не компилятор языка. Комментарий ОП подтвердил, что передача object не вызовет ошибку, а это означает, что TimedRotatingFileHandler.__init__() действительно может принять object вместо int, так что здесь нет проблем. Это не значит, что прохождение object нарушит программу.

Luke L 07.08.2024 03:04

Некоторые люди иногда просто сосредотачиваются на ответе на конкретную проблему, о которой спрашивает спрашивающий, не осознавая, что эта проблема даже не существует и не имеет значения. В этих случаях лучшее решение или ответ — сообщить спрашивающему, что его проблемы не существует, чтобы он не увяз в подобных вещах и не тратил впустую много времени. Мой ответ основан на этом, в то время как ваш ответ - один из тех, кто отлично отвечает на проблему, но не понимает, что проблему (в данном случае написание жалоб на mypy) следует опустить/игнорировать.

Luke L 07.08.2024 03:08

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

Luke L 07.08.2024 03:08

Кроме того, ваше решение может привести к тому, что программа будет работать немного медленнее, что приемлемо, если цель или причина важны, но неприемлемо, если оно просто удовлетворяет mypy или другие проблемы с типизацией. Обмануть средства проверки типов, заставив их поверить в то, что ваш тип правильный, не так хорошо, как передать все, что вы хотите, пока код работает (работает плавно, выполняет цель и свою работу и не вызывает ошибок ни сам по себе, ни TypeError, выращенный питоном).

Luke L 07.08.2024 03:13

Написание дополнительных классов только с целью ограничения типов также загрязняет пространство имен. Это нормально для небольших программ, но не совсем хорошо, если программа большая, и вы делаете это для каждого параметра функций и методов.

Luke L 07.08.2024 03:18

Приведение типов — хорошая (а иногда и необходимая) концепция в других языках программирования, таких как Java или C, но абсолютно не необходимая в Python. Помните, что Python — это динамически типизированный язык, поэтому не применяйте статически типизированные языковые привычки к динамически типизированному языку. Это не очень хорошо подходит, просто создает проблемы и шум.

Luke L 07.08.2024 03:20

Другие вопросы по теме