Type hinting in Python 2

后端 未结 3 1265
被撕碎了的回忆
被撕碎了的回忆 2020-11-27 05:09

In PEP 484, type hinting was added to Python 3 with the inclusion of the typing module. Is there any way to do this in Python 2? All I can think of is having a decorator to

相关标签:
3条回答
  • 2020-11-27 05:38

    According to Suggested syntax for Python 2.7 and straddling code in 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:

    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>
    

    For mypy support, see Type checking Python 2 code.

    0 讨论(0)
  • 2020-11-27 05:53

    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.):

    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
    
    0 讨论(0)
  • 2020-11-27 05:55

    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

    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}
    
    0 讨论(0)
提交回复
热议问题