Как манипулировать намеком встроенного типа

Как вы говорите, вам нужно показать код. : -)

Ошибка переполнения стека обычно происходит, когда ваша функция вызывает слишком много гнезд. См. Поток «Переполнение потока стека» для некоторых примеров того, как это происходит (хотя в случае этого вопроса ответы преднамеренно вызывают переполнение стека).

3
задан Azat Ibrakov 13 July 2018 в 21:09
поделиться

3 ответа

Мы можем написать функцию полезности, которая внутренне обрабатывает None -изложенные случаи и вызывает исключение / возвращает некоторое фиктивное значение данного типа:

from xml.etree.ElementTree import Element


def find(element: Element,
         tag: str) -> Element:
    result = element.find(tag)
    assert result is not None, ('No tag "{tag}" found '
                                'in element "{element}".'
                                .format(tag=tag,
                                        element=element))
    return result

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

if result is None:
    raise LookupError('No tag "{tag}" found '
                      'in element "{element}".'
                      .format(tag=tag,
                              element=element))

Отступление

Я использую аннотации типов, так как это помогает IDE, и это также экономит много времени при чтении API, но я не являюсь пользователем mypy, потому что мне не нравится идея проверять все, как в этом случае: если функция пользователя передает мусор, то это его вина, мы должны позволить ему сделать это вместо того, чтобы что-то писать о «у вас есть объединение типов и не обрабатывать случаи с некоторыми из них», EAFP после всех .

1
ответ дан Azat Ibrakov 17 August 2018 в 12:08
поделиться

Mypy не использует __annotations__, то есть конструкцию времени выполнения. Анализ Mypy полностью статичен.

«встроенные» типы (аналогичные типы из стандартной библиотеки) получены из typeshed . Если вы хотите изменить эти типы для своих целей, вы можете (хотя я бы сильно отговорил его как решение вашей проблемы). Чтобы использовать пользовательский тип с mypy, вы можете сделать mypy --custom-typeshed-dir=/path/to/my/typeshed ..., а mypy будет использовать ваш модифицированный файл.

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

1
ответ дан ethanhs 17 August 2018 в 12:08
поделиться

Я думаю, что здесь есть три разных варианта.

  1. Первым вариантом является подход, предложенный в ответе Азата Ибракова : создайте вспомогательный метод, который явно выполняет проверку «Нет» во время выполнения, чтобы удовлетворить mypy. Это наиболее типичный вариант.
  2. Второй вариант заключается в настройке mypy и ослаблении того, как он обрабатывает значения типа «Нет». В настоящее время mypy будет рассматривать «None» и «Element» как два разных типа: если у вас есть значение «None», оно не может быть «Элементом» и наоборот. Вы действительно можете ослабить это, указав mypy флаг --no-strict-optional, который сделает mypy обрабатывать значения типа «Нет» как член всех типов. Или, говоря иначе, если вы знакомы с такими языками, как Java, законно делать такие вещи, как это:
    String myString = null;
    
    Передача в флаг --no-strict-optional в mypy заставит его начать принимать код, как указано выше. Это, очевидно, означает, что ваш код будет меньше типов: mypy больше не способен обнаруживать потенциальные исключения «null pointer». Чтобы облегчить это, вы можете попробовать отключить строго-необязательный локально , а не глобально , создав конфигурационный файл mypy . В двух словах вы создадите конфигурационный файл, который выглядит примерно так:
    [mypy]
    # Global options can go here. We'll leave this empty since we don't
    # want to change any of the defaults.
    
    [mypy-mycodebase.my.xml.processing.module]
    # We weaken mypy in *just* this module
    strict_optional = False
    
  3. . Третья опция - просто прекратить использование статической типизации для вашего XML-кода синтаксического анализа в целом: отбросьте переменную root быть типа «Любой» и отправиться в город. Затем, когда вы собираете полезные данные из своего XML, выполните все необходимые проверки времени выполнения, чтобы проверить ваши данные и создать объекты (typesafe!) Для хранения соответствующей информации. (Конечно, вы можете продолжать использовать статическую типизацию для остальной части вашего кода). Наблюдение здесь заключается в том, что любой вход во время выполнения будет по своей сути динамическим: пользователь всегда может пройти в некорректном XML, данные могут быть структурированы неправильно и т. Д. Единственный реальный способ проверки этих проблем - использовать проверки времени выполнения: проверка статического типа не поможет. Итак, если проверка статического типа обеспечивает минимальное значение в определенной области кода, зачем продолжать использовать ее там? Конечно, у этой тактики есть несколько недостатков. В частности, mypy не сможет обнаружить вопиющие злоупотребления API ElementTree, вам нужно быть достаточно внимательным к проверкам времени выполнения, чтобы убедиться, что плохие данные не ползут в регионы с проверкой типов вашего кода и т. Д. .
1
ответ дан Michael0x2a 17 August 2018 в 12:08
поделиться
  • 1
    Спасибо за подробный ответ, я очень благодарен вам за добавление аргументов в каждый маршрут. – Arne 16 July 2018 в 07:43
  • 2
    @Arne: исправлено - я хотел просто закончить на & quot; это самый типичный вариант & quot; и отложил ответ Азату, но, очевидно, я пропустил заднюю мысль при корректуре ... Эх, что угодно. – Michael0x2a 16 July 2018 в 07:56
Другие вопросы по тегам:

Похожие вопросы: