47

PEP 484中,类型提示被添加到 Python 3 并包含该typing模块。有没有办法在 Python 2 中做到这一点?我所能想到的就是将装饰器添加到检查类型的方法中,但这会在运行时失败,并且不会像提示允许的那样更早被捕获。

4

3 回答 3

72

根据Python 2.7 的建议语法和定义类型提示的 PEP 484 中的跨越代码,有一种与 Python 2.7 兼容的替代语法。但是它不是强制性的,所以我不知道它的支持程度如何,但引用 PEP:

某些工具可能希望在必须与 Python 2.7 兼容的代码中支持类型注释。为此,此 PEP 有一个建议的(但不是强制性的)扩展,其中函数注释放置在 # type: 注释中。这样的注释必须紧跟在函数头之后(在文档字符串之前)。一个例子:下面的 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 代码

于 2016-02-05T18:12:10.033 回答
15

此时推荐的和 python3 兼容的方法是遵循 python2 到 3 指南: http: //python-future.org/func_annotations.html

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

变得:

def embezzle(self, account, funds = 1000000, *fake_receipts):
    """Embezzle funds from account using fake receipts."""
    pass
embezzle.__annotations__ = {'account': str, 'funds': int, 'fake_receipts': str, 'return': None}
于 2017-02-03T13:32:12.343 回答
3

这是我编写的一个函数,用于解析 Python 2 类型注释并获取输入类型和返回类型的元组。它需要一些工作来处理类型库中的复杂类型定义(Any、Optional、List 等):

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
于 2018-08-10T23:43:10.777 回答