输入提示 Python 2
Type hinting in Python 2
在PEP 484, type hinting was added to Python 3 with the inclusion of the typing
模块中。在 Python 2 中有什么办法可以做到这一点吗?我所能想到的就是有一个装饰器来添加到检查类型的方法中,但这会在运行时失败,并且不会像提示允许的那样被更早地捕获。
根据定义类型提示的 PEP 484 中的 Suggested syntax for Python 2.7 and straddling code,有一个与 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>
对于 mypy
支持,请参阅 Type checking Python 2 code。
此时推荐的 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}
这是我编写的一个函数,用于解析 Python 2 类型注释并获取输入类型和 return 类型的元组。使用类型库(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
在PEP 484, type hinting was added to Python 3 with the inclusion of the typing
模块中。在 Python 2 中有什么办法可以做到这一点吗?我所能想到的就是有一个装饰器来添加到检查类型的方法中,但这会在运行时失败,并且不会像提示允许的那样被更早地捕获。
根据定义类型提示的 PEP 484 中的 Suggested syntax for Python 2.7 and straddling code,有一个与 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>
对于 mypy
支持,请参阅 Type checking Python 2 code。
此时推荐的 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}
这是我编写的一个函数,用于解析 Python 2 类型注释并获取输入类型和 return 类型的元组。使用类型库(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