
Given that this is unlikely to see any change in core Python, perhaps you can get a decent solution with a third party library? If your main issue is that repr doesn't provide an "eval-able" string, then may I suggest using the "most-used" function in the ubelt utility library: ubelt.repr2
Two main goals of repr2 are to provide nice string representations of nested data structures and make those "eval-able" whenever possible. As an example take the value `float('inf')`, which normaly has a non-evalable repr of `inf`:
!pip install ubelt import ubelt as ub ub.repr2(float('inf'))
"float('inf')"
The `newline` (or `nl`) keyword argument can control how deep in the nesting newlines are allowed.
print(ub.repr2({1: float('nan'), 2: float('inf'), 3: 3.0}))
{ 1: float('nan'), 2: float('inf'), 3: 3.0, }
print(ub.repr2({1: float('nan'), 2: float('inf'), 3: 3.0}, nl=0))
{1: float('nan'), 2: float('inf'), 3: 3.0}
You can also define or overwrite how representations for different types are created. You can either create your own extension object, or you can monkey-patch `ub.util_format._FORMATTER_EXTENSIONS` without specifying the extensions keyword argument (although this will be a global change).
extensions = ub.FormatterExtensions() @extensions.register(float) def my_float_formater(data, **kw): return "monkey({})".format(data) print(ub.repr2({1: float('nan'), 2: float('inf'), 3: 3.0}, nl=0,
extensions=extensions)) {1: monkey(nan), 2: monkey(inf), 3: monkey(3.0)}
On Fri, Sep 4, 2020 at 12:49 PM Cade Brown brown.cade@gmail.com wrote:
I am positing that Python should contain a constant (similar to True, False, None), called Infinity.
It would be equivalent to `float('inf')`, i.e. a floating point value representing a non-fininte value. It would be the positive constant; negative infinity could retrieved via `-Infinity`
Or, to keep float representation the same, the name `inf` could be used, but that does not fit Python's normal choice for such identifiers (but indeed, this is what C uses which is the desired behavior of string conversion)
I think there are a number of good reasons for this constant. For example:
- It is also a fundamental constant (similar to True, False, and None),
and should be representable as such in the language
- Requiring a cast from float to string is messy, and also obviously
less efficient (but this performance difference is likely insignificant) * Further, having a function call for something that should be a constant is a code-smell; in general str -> float conversion may throw an error or anything else and I'd rather not worry about that.
- It would make the useful property that `eval(repr(x)) == x` for
floating point numbers (currently, `NameError: name 'inf' is not defined`)
This makes it difficult to, for example, naively serialize a list of floats. For example:
>>> x = [1, 2, 3, 4] >>> repr(x) '[1, 2, 3, 4]' >>> eval(repr(x)) == x True >>> x = [1, 2, 3, float('inf')] >>> repr(x) '[1, 2, 3, inf]' >>> eval(repr(x)) == x Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> NameError: name 'inf' is not defined
To me, this is problematic; I would expect it to work seamlessly as it does with other floating point constants.
A few rebuttals/claims against:
- Creating a new constant (Infinity) which is unassignable may break
existing code
- Converting a float to string is not the same as it is in C. Whil
I also realize that there is `math.inf`, but I argue that the constant is more fundamental than that, and it still doesn't solve the problem with `repr()` I described
Thanks,
*Cade Brown* Research Assistant @ ICL (Innovative Computing Laboratory) Personal Email: brown.cade@gmail.com ICL/College Email: cade@utk.edu
Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/XMA6KO... Code of Conduct: http://python.org/psf/codeofconduct/