I would like to propose a small class (it goes, probably, to the collections module), that will customize repr and docstring values for module constants (like math.pi or sys.maxsize). Draft implementation is available to play here: Add collections.NamedConst mixin class by skirpichev · Pull Request #22 · skirpichev/cpython · GitHub.
This will allow to use custom docstrings for constants (see issue #104042):
>>> import inspect, math
>>> math.e
math.e
>>> math.e.__doc__
'Euler number (natural logarithm base).'
>>> type(math.e)
<class 'collections._NamedFloat'>
>>> isinstance(math.e, float)
True
Cryptic literal values (like 6.283185307179586 or 9223372036854775807) also prevent using them as defaults for arguments. We already have some places in the stdlib, where such literal values are exposed and it’s obviously not a good idea to add more of them (e.g. to solve issue #89381), like this:
>>> import inspect
>>> inspect.signature(list.index)
<Signature (self, value, start=0, stop=9223372036854775807, /)>
>>> import math
>>> def mylog(x, base=math.e, /):
... return math.log(x, base)
...
>>> inspect.signature(mylog)
<Signature (x, base=2.718281828459045, /)>
With a custom repr for a constant, using such default values look more readable:
>>> import inspect, math
>>> s = inspect.signature(math.log); s
<Signature (x, base=math.e, /)>
>>> s.parameters['base'].default
math.e
>>> type(_)
<class 'collections._NamedFloat'>
Note, that such approach is already used in some places of the stdlib, e.g. the _NamedIntConstant class of the re module. Runtime cost of this should be negligible, performance impact will affect mostly module initialization.
I think it’s worth to mention the related proposal (issue #61005) to preserve original (as preferred by programmer in sources) representation for default values. Thanks to introspection capabilities of the inspect module this seems doable:
>>> import ast, inspect
>>> def foo(x=2**5 - 1):
... pass
...
>>> s = inspect.getsource(foo)
>>> t = ast.parse(s)
>>> t.body[0].args.defaults[0].lineno
1
>>> t.body[0].args.defaults[0].col_offset
10
>>> t.body[0].args.defaults[0].end_col_offset
18
>>> s.splitlines()[1-1][10:18]
'2**5 - 1'
But this seems to be a too limited solution. In general, meaning of constants can’t be easily inferred from their values (will 2**63-1 be more descriptive than 9223372036854775807?) or names (can you guess that math.tau is?).