Vous trouverez ici quelques expressions régulières avec leur “décodage” en langage humain (et ce n'est pas du luxe ).
motif = r"^[+-]?[0-9]+$"
avec:
^ -> on commence au début de la chaine [+-]? -> éventuellement un"+" ou un "-" [0-9]+ -> un ou plusieurs chiffre(s) $ -> on termine à la fin de la chaine
Bien sûr, si on veut chercher un entier dans une chaine qui contient aussi autre chose, il faut retirer les “^” et “$”.
A noter que le motif trouve aussi un nombre entier très long (comme “5555555555555555555555” par exemple) qui n'est pas un “int” en Python, mais un “long”.
motif = r"^[+-]?(([0-9]+[eE][+-]?[0-9]+)|([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)|(\.[0-9]+([eE][+-]?[0-9]+)?))$"
avec:
^ [+-]? il peut y avoir ou pas un signe ( ([0-9]+[eE][+-]?[0-9]+) si le 1er nb est entier (un ou plusieurs chiffres), alors, l'exposant est obligatoire | ([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?) si le 1er nombre (un ou plusieurs chiffre(s)) est suivi d'un point, alors les chiffres suivants et l'exposant sont optionnels | (\.[0-9]+([eE][+-]?[0-9]+)?) si on commence par un point, il y a un ou plusieurs chiffre(s) derrière, et l'exposant est optionnel ) $
Bien sûr, si on veut chercher un tel nombre (entier ou réel) dans une chaine qui contient aussi autre chose, il faut retirer les “^” et “$”.
A noter qu'on peut faire plus court, (mais encore moins clair!) en remplaçant “[0-9]” par “\d”, ce qui donne:
motif = r"^[+-]?((\d+[eE][+-]?\d+)|(\d+\.\d*([eE][+-]?\d+)?)|(\.\d+([eE][+-]?\d+)?))$"
On pourrait aussi mettre le motif de l'exposant en facteur dans les 2 derniers cas, mais cela conduirait à ajouter des parenthèses imbriquées.
Vous pouvez essayer et éventuellement modifier l'expression régulière comme vous voulez avec la boucle suivante:
motif = r"^[+-]?(([0-9]+[eE][+-]?[0-9]+)|([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)|(\.[0-9]+([eE][+-]?[0-9]+)?))$" while True: x = raw_input("x = ").strip() if x == "": break if re.match(motif, x): print u"x est un réel" else: print u"x n'est pas un réel"
On peut simplement ajouter l'option supplémentaire “est entier” à la précédente, ce qui devient:
motif = r"^[+-]?(([0-9]+)|([0-9]+[eE][+-]?[0-9]+)|([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)|(\.[0-9]+([eE][+-]?[0-9]+)?))$"
Et ce qui se lit:
^ [+-]? il peut y avoir ou pas un signe ( ([0-9]+) ça pourrait être un nombre entier | ([0-9]+[eE][+-]?[0-9]+) il pourrait y avoir un nombre entier suivi d'un exposant | ([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?) si le 1er nombre (un ou plusieurs chiffre(s)) est suivi d'un point, alors les chiffres suivants et l'exposant sont optionnels | (\.[0-9]+([eE][+-]?[0-9]+)?) si on commence par un point, il y a un ou plusieurs chiffre(s) derrière, et l'exposant est optionnel ) $
Mais, en fait, l'expression se simplifie, ce qui donne:
motif = r"^[+-]?((([0-9]+(\.[0-9]*)?)|(\.[0-9]+))([eE][+-]?[0-9]+)?)$"
Sa lecture est plus complexe, et on peut mieux la comprendre avec l'indentation:
^ [+-]? éventuellement un signe ( ( ([0-9]+(\.[0-9]*)?) on commence par un chiffre, éventuellement suivi d'un point, lui-même éventuellement suivi d'un ou plusieurs chiffres ("1." est accepté en tant que "1.0") | (\.[0-9]+) on commence par un point, suivi d'un ou plusieurs chiffre(s) (".1" est accepté en tant que "0.1", mais, bien sûr, "." est refusé) ) ([eE][+-]?[0-9]+)? et dans l'un ou l'autre des 2 cas précédents, on peut avoir éventuellement un exposant ) $
L'avantage d'utiliser les expressions régulières est ici évidente:
Et voilà une fonction qui, à partir d'une chaine, renvoie un entier, un entier long, un flottant ou False (d'après une idée de eyquem: http://www.developpez.net/forums/d656901/autres-langages/python-zope/general-python/verifier-entree-nombre/).
def numbereval(x): if re.match(r"^[+-]?[0-9]+[lL]?$", x): if x!="" and x[-1] in "lL": return long(x[:-1]) else: return int(x) elif re.match(r"^[+-]?(([0-9]+[eE][+-]?[0-9]+)|([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)|(\.[0-9]+([eE][+-]?[0-9]+)?))$", x): return float(x) else: return False
Cette fonction détecte un entier long de 2 façon différentes:
Et voilà le code pour le tester:
while True: y = numbereval(raw_input('x =').strip()) if y: print type(y), y else: print u"ce n'est pas un nombre"
Amusez-vous bien!