Ввод кортежа или списка кортежей в рекурсивной функции

Вот пример, который я написал.

from typing import Tuple, List


def performances(
    pt: Tuple[float, float] | List[Tuple[float, float]]
) -> float | list[float]:
    if isinstance(pt, list):
        output = []
        for pt_i in pt:
            output.append(performances(pt_i))
    else:
        output = pt[0] + pt[1]
    return output


if __name__ == "__main__":

    # This work as intended
    t1 = performances((1, 2))
    print(t1)

    # This work as intended
    t2 = performances([(1, 2), (3, 4)])
    print(t2)

    # This work while I was expecting it to throw a TypeError
    t3 = performances((1, 2, 3, 4))
    print(t3)

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

Я также пробовал без типов Tuple и List из typing, просто используя list[tuple[float, float]], но результат тот же.

И:

from typing import Tuple, Iterable

type Point = Tuple[float, float]

def performances(pt: Point | Iterable[Point]) -> float | list[float]:
...

Но то же самое.

Наверное, я чего-то не понимаю в наборе текста, но не знаю, что именно. Спасибо.

Используете ли вы проверку типов для проверки этого? Python по своей сути не проверяет ошибки типов.

Poojan 03.09.2024 05:11

Я использую Pytest для некоторого модульного тестирования моего кода, и этот конкретный тест проходит успешно, в то время как раньше мне приходилось отклонять тест из-за ошибок типа (я думаю? Может быть, это не так).

Romn 03.09.2024 05:13

В Python аннотации типов не являются обязательными и, к сожалению, могут быть совершенно неверными. Отдельные приложения, такие как mypy илиpyright, позволяют использовать аннотации для статического анализа кода и, при условии корректности аннотаций, предупреждают вас об ошибках. Однако во время выполнения эти аннотации обычно полностью игнорируются (за исключением таких библиотек, как Pydantic, которые используют аннотации для логического управления). Pytest отвечает только за выполнение тестовых операторов и проверку утверждений. Pytest не проверяет корректность аннотаций типов.

flakes 03.09.2024 05:34

Если вы хотите иметь возможность проверять эти типы во время выполнения, этот вопрос может быть полезен: извлечение данных из типизированных типов

Anerdw 03.09.2024 05:35

в чем конкретно заключается ваш вопрос? В чем проблема?

juanpa.arrivillaga 03.09.2024 06:16

Я думал, что хинтинг типов вызовет ошибку TypeError, но теперь я понял, что мне нужно проверить это с помощью средства проверки типов, например mypy. Теперь у меня есть ошибки, показанные в ответе ниже, и мне интересно, как их исправить.

Romn 03.09.2024 06:21
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
7
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Типы выходных данных имеют два различных результата в зависимости от параметров. pt: Tuple[float, float] ведет к float, тогда как pt: List[Tuple[float, float]] ведет к List[float].

Mypy и другие инструменты статического анализа не имеют хорошего способа определить, какая входная форма должна привести к какой выходной форме. Это приводит к ошибкам при вызове append(performances(pt_i)), поскольку ваши инструменты статического анализа будут думать, что вы пытаетесь создать List[Union[float, List[float]]].

Хороший способ исправить это — использовать @overload из модуля набора текста.

from typing import Tuple, List, overload


@overload
def performances(pt: Tuple[float, float]) -> float:
    ...


@overload
def performances(pt: List[Tuple[float, float]]) -> List[float]:
    ...


def performances(
    pt: Tuple[float, float] | List[Tuple[float, float]]
) -> float | list[float]:
    if isinstance(pt, list):
        return list(map(performances, pt))
    return pt[0] + pt[1]

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

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