Python 2 中的类型提示

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35230635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 16:09:37  来源:igfitidea点击:

Type hinting in Python 2

pythonpython-2.7typestype-hinting

提问by Andrew

In PEP 484, type hinting was added to Python 3 with the inclusion of the typingmodule. Is there any way to do this in Python 2? All I can think of is having a decorator to add to methods to check types, but this would fail at runtime and not be caught earlier like the hinting would allow.

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

采纳答案by Mijamo

According to Suggested syntax for Python 2.7 and straddling codein PEP 484 which defined type hinting, there is an alternative syntax for compatibility with Python 2.7. It is however not mandatory so I don't know how well supported it is, but quoting the PEP:

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

Some tools may want to support type annotations in code that must be compatible with Python 2.7. For this purpose this PEP has a suggested (but not mandatory) extension where function annotations are placed in a # type: comment. Such a comment must be placed immediately following the function header (before the docstring). An example: the following Python 3 code:

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

is equivalent to the following:

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

某些工具可能希望在必须与 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>

For mypysupport, see Type checking Python 2 code.

如需mypy支持,请参阅类型检查 Python 2 代码

回答by encolpe

At this point the recommended and python3 compatible way to do is to follow the python2 to 3 guide : http://python-future.org/func_annotations.html

此时推荐的和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

Become:

变得:

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}

回答by Thomas Belluscio

Here is a function i wrote to parse the Python 2 type comment and get a tuple of input types and the return type. It would need some work to work with complex type definitions from the typing library (Any, Optional, List, etc.):

这是我编写的一个函数,用于解析 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