28. globalformat — Set global ouput format for built-in types.

One of the major shortcomings of Python is the lack of global print options allowing to set the output format for built-in type globally for your application. Especially the default formatting of float values is annoyingly large.

>>> sqrt2 = 2 ** 0.5
>>> print(sqrt2)
1.4142135623730951

To get a shorter output with less decimals one can round the value, or use a format specifier:

>>> print(round(sqrt2, 4))
1.4142
>>> print(f"{sqrt2:.4f}")
1.4142

But this is only convenient when you have to output a single float, but doesn’t work for floats embedded in a container.

>>> cont = (1/2, 1/3, 1/16)
>>> print(cont)
(0.5, 0.3333333333333333, 0.0625)

Luckily, for most numerical work we can (and should) use NumPy, which allows to set global print options for its classes:

>>> import numpy as np
>>> np.set_printoptions(precision=4, floatmode='fixed')
>>> ar = np.array(cont)
>>> print(ar)
[0.5000 0.3333 0.0625]

But even then one falls back to the Python default for a single array element:

>>> print(ar[0], ar[1])
0.5 0.3333333333333333

The solution would be to override float.__repr__, but Python won’t let you:

>>> float.__repr__ = lambda f: f"{f:.4f}"
Traceback (most recent call last):
...
TypeError: cannot set '__repr__' attribute of immutable type 'float'

But since this is Python, there must be some way to overcome this hurdle. And I finally found one: the forbiddenfruit module (https://pypi.org/project/forbiddenfruit/) by Lincoln de Sousa <lincoln@clarete.li> allows to do all kinds of monkeypatching on builtin types. Since we only need a small part of it, we copied the relevant things in this module, thus avoiding that our users need to install that module. Now we can set our own float.__repr__ method, which can take account of a global precision setting.

>>> setfloatformat('.4f')        # set fixed format for all floats
>>> print(cont)
(0.5000, 0.3333, 0.0625)
>>> setfloatformat('')           # reset Python's default
>>> print(cont)
(0.5, 0.3333333333333333, 0.0625)

Or you can use the floatformat context manager to temporarily change the format:

>>> with floatformat('.4f'):
...    print('.4f', cont)
...    with floatformat('10.2e'):
...        print('10.2e', cont)
...    print('back to .4f', cont)
.4f (0.5000, 0.3333, 0.0625)
10.2e (  5.00e-01,   3.33e-01,   6.25e-02)
back to .4f (0.5000, 0.3333, 0.0625)
>>> print('back to default', cont)
back to default (0.5, 0.3333333333333333, 0.0625)

28.1. Classes defined in module globalformat

class globalformat.floatformat(fmt)[source]

Context manager to temporarily change the global float format.

Parameters:

fmt (str) – A format string like in setfloatformat().

Notes

On exit, the global float format is reset to what is was before entering.

28.2. Functions defined in module globalformat

globalformat.setfloatformat(fmt)[source]

Set global default format for float

Parameters:

fmt (str) – A format string to format a single float number. For example: ‘.4f’ will format the float with 4 decimals. An empty string resets the format to Python’s default. An invalid format string raises an Exception.