Можно ли использовать оператор Python Walrus для универсальных функций подсказки типа?

Предположим, я хочу ввести подсказку для универсальной функции в Python до версии 3.12, когда был введен новый синтаксис параметров:

def max[T](args: Iterable[T]) -> T:
    ...

Затем у меня есть возможность использовать подсказки строкового типа:

def max(args: Iterable["T"]) -> "T":
    ...

Или введите переменные:

T = TypeVar("T")

def max(args: Iterable[T]) -> T:
    ...

Мне больше нравится последний подход, но введение дополнительной глобальной переменной определенно является недостатком. Я решил объединить хинтинг универсального типа с оператором моржа, вот так:

def max(args: Iterable[T := TypeVar("T")]) -> T:
    ...

Или

def max(args: Iterable[T := int | float]) -> T:
    ...

Подобный код выполняется без ошибок, но некоторые библиотеки типизации не распознают этот синтаксис. Каковы недостатки написания такого кода?

Этот вопрос следует отредактировать, чтобы он сосредоточился только на одной проблеме и не требовал рекомендаций.

InSync 15.03.2024 17:17
T по-прежнему глобальный; вы просто переместили определение и засорили сигнатуру функции. Хуже того, не будет очевидно, что вы переопределили T, когда попробуете тот же трюк в другой функции.
chepner 15.03.2024 19:32

«Тогда у меня есть возможность использовать подсказки строкового типа:» На самом деле это работает не так, как другие примеры. Он просто позволяет избежать ошибки во время выполнения, но не создает переменную типа T, как в других примерах. Аналогично, T := int | float не определяет переменную типа.

MisterMiyagi 17.03.2024 08:21

«Подобный код выполняется без ошибок, но некоторые библиотеки типов не распознают этот синтаксис». Вы действительно нашли какую-либо программу проверки типов, которая принимает это? И MyPy, и PyLance отвергают варианты моржа.

MisterMiyagi 17.03.2024 08:31

@chepner Правда, я не осознавал, что T всё равно будет глобальным. Но переопределение T не является проблемой, поскольку я никогда не получаю доступа к его значению, и оно генерирует сигнатуры функций, как и ожидалось. Загромождение сигнатуры является недостатком, но, с другой стороны, объединение определения typevar вместе с определением функции имеет смысл.

Dima 18.03.2024 12:06
Почему в 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
5
152
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

  • Пока система типов развивается (к лучшему!) так, как она есть.
  • Когда вы не контролируете среду, ваш код запускается/проверяется (например, распределенная команда)

Я бы выбрал совместимость со стандартными инструментами: это убережет ваших коллег от многих сюрпризов. Так вот: никаких моржей в намеках типа :).

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

Видимо, по какой-то причине это не вошло в документацию, но ваш вопрос рассмотрен в PEP484:

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

Таким образом, специалисты по проверке типов должны отклонить предложенный вами фрагмент. mypyделает , Pyright тоже делает , и Pyre тоже делает.

Итак, основным недостатком написания такого кода является тот факт, что такой код несовместим и неправильно интерпретируется средствами проверки типов.

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

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