Come faccio a controllare il numero di formattare l'interprete Python?
Domanda
Io uso spesso l'interprete Python per fare calcoli numerici rapidi e vorrei tutti i risultati numerici da stampare automaticamente utilizzando, per esempio, la notazione esponenziale. C'è un modo per impostare questo per l'intera sessione?
Per esempio, io voglio:
>>> 1.e12
1.0e+12
non
>>> 1.e12
1000000000000.0
Soluzione
Creare uno script Python chiamato quello che vuoi (mystartup.py
diciamo) e quindi impostare un ambiente PYTHONSTARTUP
variabile al percorso di questo script. Python quindi caricare questo script all'avvio di una sessione interattiva (ma non quando l'esecuzione di script). In questo script, definire una funzione simile a questo:
def _(v):
if type(v) == type(0.0):
print "%e" % v
else:
print v
Poi, in una sessione interattiva:
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 >>>
Naturalmente, è possibile definire la funzione di essere chiamato whaetver che si desidera e di lavorare esattamente come vuoi.
Anche meglio di questa potrebbe essere quella di utilizzare IPython . E 'grande, ed è possibile impostare il numero di formattazione come si desidera utilizzando result_display.when_type(some_type)(my_print_func)
(si veda il sito IPython oppure cerca altri dettagli su come usare questo).
Altri suggerimenti
Hm ... Non è una soluzione 100%, ma questo sono venuti in mente ...
Come sulla definizione di una sottoclasse di galleggiante che avrebbe un metodo __str__
sovrascritto (per stampare con la notazione exp). E poi si dovrebbe avvolgere tutte le espressioni con la costruzione oggetto di questa classe).
Sarebbe un po 'più breve rispetto alla soluzione di Dave, si potrebbe definire la classe di una volta e poi scrivere qualcosa come:
>>> F(1.e12)
1.0e+12
>>> F(3.)
3.0e+0
>>> F(1.+2.+3.+4.)
1.0e+1
...
Come sapete è possibile utilizzare l'operatore %
o str.format
per stringhe di formato:
Ad esempio:
>>> "%e" % 1.e12
'1.000000e+12'
Mi chiedevo se si potesse la classe incorporata float
per cambiare il formattazione ma sembra che Python non ti consente di:
>>> 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'
Quindi, l'unica altra cosa che posso pensare è quello di scrivere il proprio oggetto simile a file che cattura l'uscita, riformatta e lo invia sullo standard output. Farebbe quindi ridirezionare l'output standard dell'interprete a questo oggetto:
sys.stdout = my_formatting_object
Sulla suggerimento di Dave Webb sopra. Ovviamente si può impostare la precisione, se ti piace ( "% .3e") e forse ignorare writelines se necessario.
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()
e l'uso di:
>>> 14000
1.400000e+04
>>> "text"
'text'
Quando si utilizza IPython / Jupyter-console, la "magia" di comando %precision %e
cambierà la visualizzazione dei carri prime in notazione esponenziale. https://ipython.readthedocs.io/en/stable/ interattivo / magics.html # magic-precisione
Per un maggiore controllo della formattazione, un formattatore può essere registrato:
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)))
Ci scusiamo per necroposting, ma questo argomento si presenta nelle ricerche Google Related e credo che una risposta soddisfacente manca qui.
Credo che la strada giusta è quella di utilizzare sys.displayhook
. Ad esempio, è possibile aggiungere il codice come questo nel file PYTHONSTARTUP
:
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
Questo mostrerà i valori abbastanza grande utilizzando la sintassi exp. Sentitevi liberi di modificare la soglia, come si vede in forma.
In alternativa si può avere la risposta stampato in entrambi i formati per grandi numeri:
def __displayhook(value):
__orig_hook(value)
if isinstance(value, numbers.Number) and value >= 1e5:
print("{:e}".format(value))
In alternativa, è possibile definire se stessi un'altra variabile risposta oltre al _
predefinito, ad esempio __
(quali la creatività, lo so):
builtins.__ = None
__orig_hook = sys.displayhook
def __displayhook(value):
if isinstance(value, numbers.Number):
builtins.__ = "{:e}".format(value)
__orig_hook(value)
sys.displayhook = __displayhook
... e quindi visualizzare la risposta exp-formattato digitando semplicemente __
.