
I think you are going against the design of the language here. With only
a handful of critical exceptional cases (None, True, False are the only
ones that come to mind), names can be rebound.
The following genuinely surprised me. I was trying to show something different in reply, but I think the actual behavior makes the point even more:
eval(repr(Ellipsis))
Ellipsis
eval(repr(...))
Ellipsis
Ellipsis = 42 eval(repr(...))
42
This is *strange* behavior. I don't expect every sequence of characters to round trip `eval(repr())`, but I kinda expect it to be mostly idempotent.
foo = "bar" eval(repr(foo))
'bar'
eval(repr(foo)) == eval(repr(eval(repr(foo))))
True
eval(repr(None)) == eval(repr(eval(repr(None))))
True
Obviously I know there are some repr()'s that cannot be eval()'d. But this isn't the same concern as e.g. a file handle or a user class.
I don't find this issue any huge wart in Python, but it's a funny corner. Here's a proposal I'll throw out:
Let's change the behavior of the Ellipsis object slightly to have either a .__call__() or .__getitem__() method that returns itself, no matter what argument is passed.
Then we could have this behavior:
repr(...)
...[Ellipsis]
Or
repr(...)
...(Ellipsis)
I don't know which looks better, but neither look terrible to me. That would produce a more explanatory repr() while also preserving idempotence.