57

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 add to methods to check types, but this would fail at runtime and not be caught earlier like the hinting would allow.

InSync
12.2k5 gold badges22 silver badges60 bronze badges
asked Feb 5, 2016 at 18:02
0

3 Answers 3

85

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.

answered Feb 5, 2016 at 18:12
Sign up to request clarification or add additional context in comments.

10 Comments

Hmm ok, should have read the docs further. Do you know if there any tools that currently support this? Not sure if it is just a standard or if there is actual tooling implemented yet.
According to PyCharm "PyCharm supports type hinting in function annotations and type comments using the typing module defined by PEP 484." The reference to TYPE COMMENTS makes it clear that it should be supported. I don't use pyCharm on this computer so I cannot check it right now. EDIT : link to pycharm: jetbrains.com/pycharm/help/…
Thanks, also found that Emacs Jedi works with it as well.
A bit off-topic: perhaps you know how could I extract this type annotation in Python 2? It's not included in __doc__ attr and __annotations__ attr is not available in Python 2.
Will this work on earlier versions of Python 3 as well?
|
17

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}
answered Feb 3, 2017 at 13:32

1 Comment

this will not work for non-literal types like List, Set
3

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
answered Aug 10, 2018 at 23:43

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.