hinting - python type hints in comments




Тип подсказок в Python 2 (2)

В соответствии с Предложенным синтаксисом для Python 2.7 и стандартным кодом в PEP 484, который определил хинтинг типов, существует альтернативный синтаксис для совместимости с Python 2.7. Это, однако, не является обязательным, поэтому я не знаю, насколько хорошо это поддерживается, но цитирую PEP:

Некоторые инструменты могут захотеть поддерживать аннотации типов в коде, который должен быть совместим с Python 2.7. Для этой цели этот PEP имеет предлагаемое (но не обязательное) расширение, где аннотации функций помещаются в # type: comment. Такой комментарий должен быть размещен сразу после заголовка функции (перед строкой документации). Пример: следующий код Python 3:

def embezzle(self, account: str, funds: int = 1000000, *fake_receipts: str) -> None:
    """Embezzle funds from account using fake receipts."""
    <code goes here>

эквивалентно следующему:

def embezzle(self, account, funds=1000000, *fake_receipts):
    # type: (str, int, *str) -> None
    """Embezzle funds from account using fake receipts."""
    <code goes here>

Для поддержки mypy , смотрите Проверка типов кода Python 2 .

В PEP 484 подсказка типа была добавлена ​​в Python 3 с включением модуля typing . Есть ли способ сделать это в Python 2? Все, что я могу придумать, это иметь декоратор для добавления в методы для проверки типов, но это не сработает во время выполнения и не будет перехвачено ранее, как позволяет подсказка.


Вот функция, которую я написал для анализа комментария типа Python 2 и получения кортежа типов ввода и возвращаемого типа. Потребовалась бы некоторая работа для работы с определениями сложных типов из библиотеки ввода (Любой, Необязательный, Список и т. Д.):

class InvalidTypeHint(Exception):
    pass    

PYTHON_2_TYPE_HINT_REGEX = "\s*#\s*type:\s*(\(.+\))\s*->\s*(.+)\s*"

def parse_python_2_type_hint(typehint_string):
    # type: (str) -> (tuple, type)
    pattern = re.compile(PYTHON_2_TYPE_HINT_REGEX)
    search_results = pattern.search(typehint_string)
    if not search_results:
        raise InvalidTypeHint('%s does not match type hint spec regex %s' % (typehint_string, PYTHON_2_TYPE_HINT_REGEX))
    arg_types_str = search_results.group(1)
    return_type_str = search_results.group(2)
    try:
        arg_types_tuple = eval(arg_types_str)
        assert isinstance(arg_types_tuple, tuple)
        return_type = eval(return_type_str)
        assert isinstance(return_type, type)
    except Exception as e:
        raise InvalidTypeHint(e)
    return arg_types_tuple, return_type


def parse_arg_types_for_callable(func):
    # type:(callable)->tuple
    """

    :param func:
    :return: list of parameter types if successfully parsed, else None
    """

    # todo make this compatible with python 3 type hints
    # python 2.7 type hint
    source_lines = inspect.getsource(func).split("\n")
    def_statements = 0
    for source_line in source_lines:
        try:
            arg_types_tuple, return_type = parse_python_2_type_hint(source_line)
            return arg_types_tuple
        except InvalidTypeHint:
            if source_line.strip().startswith("def "):
                def_statements += 1
            if def_statements > 1:
                return None






type-hinting