Декоратор перегрузки в модуле набора текста, похоже, не работает должным образом - PullRequest
0 голосов
/ 27 августа 2018
>>> from typing import overload

>>> @overload
... def hello(s: int):
...     return "Got an integer!"

>>> def hello(s: str):
...     return "Got a string"

Почему вызывающий hello(1) вызывает функцию со строковым аргументом?В идеале оператор @overload должен с этим справиться, верно?

1 Ответ

0 голосов
/ 27 августа 2018

К сожалению, python не допускает перегрузки функций.Каждый раз, когда вы думаете, что перегружаете функцию, вы просто перезаписываете предыдущее объявление функции.Цитата из docs :

Декоратор @overload позволяет описывать функции и методы, которые поддерживают несколько различных комбинаций типов аргументов.За серией определений с @ перегрузкой должно следовать ровно одно определение без @ перегрузки (для той же функции / метода). Определения с @ перегрузкой предназначены только для проверки типов, поскольку они будут перезаписаны определением без @ перегрузки, в то время как последнее используется во время выполнения, но должно игнорироваться средством проверки типов .Во время выполнения прямой вызов функции с декором @ overload вызовет NotImplementedError.

Правильное использование typing.overload выглядит следующим образом:

from typing import overload


@overload
def hello(s: int) -> str:
    ...


@overload
def hello(s: str) -> str:
    ...


def hello(s):
    if isinstance(s, int):
        return "Got an integer!"
    if isinstance(s, str):
        return "Got a string"
    raise ValueError('You must pass either int or str')


if __name__ == '__main__':
    print(hello(1))

Чтобы показать фактическое преимуществоtyping.overload позволяет изменить def hello(s: int) для возврата int вместо str:

from typing import overload


@overload
def hello(s: int) -> int:
    ...


@overload
def hello(s: str) -> str:
    ...


def hello(s):
    if isinstance(s, int):
        return "Got an integer!"
    if isinstance(s, str):
        return "Got a string"
    raise ValueError('You must pass either int or str')


if __name__ == '__main__':
    print(hello(1))
    a = hello(1) + 1
    b = hello(1) + 'a'

Обратите внимание, что фактическая реализация по-прежнему возвращает str - Python здесь не выполняет никаких проверок.Однако PyCharm выдает предупреждение:

enter image description here

mypy также жалуется на недопустимые типы:

➜ mypy test.py 
test.py:25: error: Unsupported operand types for + ("int" and "str")

Цель *Модуль 1034 * позволяет сторонним инструментам выполнять статическую проверку вашего кода.Здесь нет магии - все типы игнорируются во время выполнения.

...