Comment contrôler le formatage des nombres dans l'interpréteur Python?
Question
J'utilise souvent l'interpréteur Python pour effectuer des calculs numériques rapides et je voudrais que tous les résultats numériques soient automatiquement imprimés en utilisant, par exemple, une notation exponentielle. Existe-t-il un moyen de définir ceci pour toute la session?
Par exemple, je veux:
>>> 1.e12
1.0e+12
ne pas:
>>> 1.e12
1000000000000.0
La solution
Créez un script Python appelé comme vous voulez (dire mystartup.py
) puis définir une variable d'environnement PYTHONSTARTUP
sur le chemin de ce script. Python chargera ensuite ce script au démarrage d'une session interactive (mais pas lors de l'exécution de scripts). Dans ce script, définissez une fonction similaire à ceci:
def _(v):
if type(v) == type(0.0):
print "%e" % v
else:
print v
Ensuite, dans une session interactive:
C:\temp>set PYTHONSTARTUP=mystartup.py C:\temp>python ActivePython 2.5.2.2 (ActiveState Software Inc.) based on Python 2.5.2 (r252:60911, Mar 27 2008, 17:57:18) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> _(1e12) 1.000000e+012 >>> _(14) 14 >>> _(14.0) 1.400000e+001 >>>
Bien sûr, vous pouvez définir la fonction à appeler ce que vous voulez et travailler exactement comme vous le souhaitez.
Encore mieux que cela serait à utiliser Ipython. C'est génial, et vous pouvez définir le formatage du numéro comme vous le souhaitez en utilisant result_display.when_type(some_type)(my_print_func)
(Voir le site Ipython ou rechercher plus de détails sur la façon de l'utiliser).
Autres conseils
HM ... ce n'est pas une solution à 100%, mais cela est venu à mon esprit ...
Que diriez-vous de définir une sous-classe de flotteur qui aurait un remplacement __str__
Méthode (à imprimer avec la notation Exp). Et puis il faudrait envelopper toutes les expressions avec la construction d'objets de cette classe). Ce serait un peu plus court que la solution de Dave, vous définissez la classe une fois, puis écririez quelque chose comme:
>>> F(1.e12)
1.0e+12
>>> F(3.)
3.0e+0
>>> F(1.+2.+3.+4.)
1.0e+1
...
Comme vous le savez, vous pouvez utiliser la %
opérateur ou str.format
Pour formater les chaînes:
Par exemple:
>>> "%e" % 1.e12
'1.000000e+12'
Je me demandais si vous pouviez patch le intégré float
classe pour changer le formatage, mais il semble que Python ne vous laisse pas:
>>> 1.e12.__class__.__repr__ = lambda x: "%e" % x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'float'
Ainsi, la seule autre chose à laquelle je peux penser est d'écrire votre propre objet de type fichier qui capture la sortie, le reformats et l'envoie à la sortie standard. Vous redirigeriez ensuite la sortie standard de l'interprète vers cet objet: vous
sys.stdout = my_formatting_object
S'appuyant sur l'indice de Dave Webb ci-dessus. Vous pouvez bien sûr définir la précision si vous le souhaitez ("% .3e") et peut-être remplacer les écrivains si nécessaire.
import os
import sys
class ExpFloatFileObject:
def write(self, s):
try:
s = "%e"%float(s)
except ValueError:
pass
sys.__stdout__.write(s)
def __getattr__(self, name):
return getattr(sys.__stdout__, name)
sys.stdout = ExpFloatFileObject()
et utilisation:
>>> 14000
1.400000e+04
>>> "text"
'text'
Lorsque vous utilisez Ipython / Jupyter-Console, la commande "Magic" %precision %e
changera l'affichage des flotteurs bruts en notation exponentielle. https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-precision
Pour plus de contrôle de formatage, un formateur peut être enregistré:
excited_floats = lambda val: "{:e}!!!".format(val)
console_formatter = get_ipython().display_formatter.formatters['text/plain']
console_formatter.for_type(float, lambda val, p, c: p.text(excited_floats(val)))
Désolé pour la nécropostage, mais ce sujet apparaît dans les recherches Google connexes et je crois qu'une réponse satisfaisante est manquante ici.
Je crois que la bonne façon est d'utiliser sys.displayhook
. Par exemple, vous pouvez ajouter du code comme celui-ci dans votre PYTHONSTARTUP
dossier:
import builtins
import sys
import numbers
__orig_hook = sys.displayhook
def __displayhook(value):
if isinstance(value, numbers.Number) and value >= 1e5:
builtins._ = value
print("{:e}".format(value))
else:
__orig_hook(value)
sys.displayhook = __displayhook
Cela affichera des valeurs suffisamment grandes à l'aide de la syntaxe EXP. N'hésitez pas à modifier le seuil comme bon vous semble.
Alternativement, vous pouvez faire imprimer la réponse dans les deux formats pour de grands nombres:
def __displayhook(value):
__orig_hook(value)
if isinstance(value, numbers.Number) and value >= 1e5:
print("{:e}".format(value))
Ou vous pouvez vous définir une autre variable de réponse en plus de la valeur par défaut _
, tel que __
(Une telle créativité, je sais):
builtins.__ = None
__orig_hook = sys.displayhook
def __displayhook(value):
if isinstance(value, numbers.Number):
builtins.__ = "{:e}".format(value)
__orig_hook(value)
sys.displayhook = __displayhook
... puis afficher la réponse Exp format en tapant juste __
.