Dans PEP 484 , une indication de type a été ajoutée à Python 3 avec l'inclusion du module typing
. Existe-t-il façon de le faire dans Python 2? Tout ce que je peux penser, c'est d'avoir un décorateur à ajouter aux méthodes pour vérifier les types, mais cela échouerait au moment de l'exécution et ne serait pas détecté plus tôt comme l'indiquerait l'indication .
Selon Syntaxe suggérée pour Python 2.7 et code chevauchant dans PEP 484 qui définit le type laissant entendre, il existe une syntaxe alternative pour la compatibilité avec Python 2.7. Elle n'est cependant pas obligatoire, donc je ne sais pas si elle est bien prise en charge, mais en citant le PEP:
Certains outils peuvent vouloir prendre en charge les annotations de type dans du code qui doit être compatible avec Python 2.7. À cette fin, ce PEP a une extension suggérée (mais pas obligatoire) où les annotations de fonction sont placées dans un type # : comment. Un tel commentaire doit être placé immédiatement après l'en-tête de la fonction (avant la docstring). Un exemple: le code Python 3 suivant:
def embezzle(self, account: str, funds: int = 1000000, *fake_receipts: str) -> None: """Embezzle funds from account using fake receipts.""" <code goes here>
est équivalent à ce qui suit:
def embezzle(self, account, funds=1000000, *fake_receipts): # type: (str, int, *str) -> None """Embezzle funds from account using fake receipts.""" <code goes here>
Pour la prise en charge de mypy
, voir ( Vérification de type Python 2 .
À ce stade, la manière recommandée et compatible avec python3 est de suivre le guide python2 to 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
Devenir:
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}
Voici une fonction que j'ai écrite pour analyser le commentaire de type Python 2 et obtenir un tuple de types d'entrée et le type de retour. Il faudrait du travail pour travailler avec des définitions de types complexes de la bibliothèque de typage ( Tout, Facultatif, Liste, 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