The name Ellipsis should be a constant
In Python `...` is referred to as `Ellipsis` and cannot be assigned to. Yet, one can assign any value to the name `Ellipsis`. Consider the following: ```
... Ellipsis ... == Ellipsis True Ellipsis Ellipsis Ellipsis = 3 Ellipsis 3 ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis # But I just did assign a new value to the name Ellipsis above. Ellipsis 3 ... Ellipsis ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same
object that `...` refers to, so that both could not be assigned a new value.
André Roberge
On Mon, 2021-05-31 at 11:37 -0300, André Roberge wrote:
In Python `...` is referred to as `Ellipsis` and cannot be assigned to. Yet, one can assign any value to the name `Ellipsis`.
Consider the following:
```
... Ellipsis ... == Ellipsis True Ellipsis Ellipsis Ellipsis = 3 Ellipsis 3 ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis # But I just did assign a new value to the name Ellipsis above. Ellipsis 3 ... Ellipsis ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
Perhaps Ellipsis could get the same treatment as None here, but I am not sure if there's enough reasoning to justify that, especially considering that it would be a backwards incompatible change. Do you have any use-cases that would warrant such a thing? I find it incredibly hard to justify this proposal. Cheers, Filipe Laíns
If you're proposing prevention of monkey patching Ellipsis, I think you'll have to go all-in on all builtins. For example:
str = int str <class 'int'> str == int True
Paul On Mon, 2021-05-31 at 11:37 -0300, André Roberge wrote:
In Python `...` is referred to as `Ellipsis` and cannot be assigned to. Yet, one can assign any value to the name `Ellipsis`.
Consider the following:
```
... Ellipsis ... == Ellipsis True Ellipsis Ellipsis Ellipsis = 3 Ellipsis 3 ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis # But I just did assign a new value to the name Ellipsis above. Ellipsis 3 ... Ellipsis ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value. André Roberge _______________________________________________ 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/KDQ3OHALLXVZJIGPC4BMPVS2XH3VFPJV/ Code of Conduct: http://python.org/psf/codeofconduct/
On 2021-05-31 15:55, Paul Bryan wrote:
If you're proposing prevention of monkey patching Ellipsis, I think you'll have to go all-in on all builtins.
For example:
str = int
str
<class 'int'>
str == int
True
If you rebind str to int, the repr of str will say <class 'int'>, so you can tell that something's happened, but the repr of ... is always 'Ellipsis', even though you've rebound Ellipsis.
On Mon, 2021-05-31 at 11:37 -0300, André Roberge wrote:
In Python `...` is referred to as `Ellipsis` and cannot be assigned to. Yet, one can assign any value to the name `Ellipsis`.
Consider the following:
```
... Ellipsis ... == Ellipsis True Ellipsis Ellipsis Ellipsis = 3 Ellipsis 3 ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis # But I just did assign a new value to the name Ellipsis above. Ellipsis 3 ... Ellipsis ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
On 2021-05-31 16:16:59, MRAB wrote:
If you rebind str to int, the repr of str will say <class 'int'>, so you can tell that something's happened, but the repr of ... is always 'Ellipsis', even though you've rebound Ellipsis.
Ellipsis is ... True Ellipsis = str Ellipsis is ... False
Because ... is still bound to the original Ellipsis. Just as "s" below will remain bound to the original str.
s = str str = int int <class 'int'> s <class 'str'>
Paul On Mon, 2021-05-31 at 16:16 +0100, MRAB wrote:
On 2021-05-31 15:55, Paul Bryan wrote:
If you're proposing prevention of monkey patching Ellipsis, I think you'll have to go all-in on all builtins.
For example:
str = int
str
<class 'int'>
str == int
True
If you rebind str to int, the repr of str will say <class 'int'>, so you can tell that something's happened, but the repr of ... is always 'Ellipsis', even though you've rebound Ellipsis.
On Mon, 2021-05-31 at 11:37 -0300, André Roberge wrote:
In Python `...` is referred to as `Ellipsis` and cannot be assigned to. Yet, one can assign any value to the name `Ellipsis`.
Consider the following:
```
... Ellipsis ... == Ellipsis True Ellipsis Ellipsis Ellipsis = 3 Ellipsis 3 ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis # But I just did assign a new value to the name Ellipsis above. Ellipsis 3 ... Ellipsis ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
_______________________________________________ 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/NE2FAW... Code of Conduct: http://python.org/psf/codeofconduct/
Fixing typo:
s = str str = int str <class 'int'> s <class 'str'>
On Mon, 2021-05-31 at 08:31 -0700, Paul Bryan wrote:
Because ... is still bound to the original Ellipsis. Just as "s" below will remain bound to the original str.
s = str str = int int <class 'int'> s <class 'str'>
Paul
On Mon, 2021-05-31 at 16:16 +0100, MRAB wrote:
On 2021-05-31 15:55, Paul Bryan wrote:
If you're proposing prevention of monkey patching Ellipsis, I think you'll have to go all-in on all builtins.
For example:
str = int
str
<class 'int'>
str == int
True
If you rebind str to int, the repr of str will say <class 'int'>, so you can tell that something's happened, but the repr of ... is always 'Ellipsis', even though you've rebound Ellipsis.
On Mon, 2021-05-31 at 11:37 -0300, André Roberge wrote:
In Python `...` is referred to as `Ellipsis` and cannot be assigned to. Yet, one can assign any value to the name `Ellipsis`.
Consider the following:
```
> ... Ellipsis > ... == Ellipsis True > Ellipsis Ellipsis > Ellipsis = 3 > Ellipsis 3 > ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis > # But I just did assign a new value to the name > Ellipsis above. > Ellipsis 3 > ... Ellipsis > ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
_______________________________________________ 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/NE2FAW... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ 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/UTNK34... Code of Conduct: http://python.org/psf/codeofconduct/
On Mon, May 31, 2021 at 12:20 PM MRAB <python@mrabarnett.plus.com> wrote:
On 2021-05-31 15:55, Paul Bryan wrote:
If you're proposing prevention of monkey patching Ellipsis, I think you'll have to go all-in on all builtins.
For example:
str = int
str
<class 'int'>
str == int
True
If you rebind str to int, the repr of str will say <class 'int'>, so you can tell that something's happened, but the repr of ... is always 'Ellipsis', even though you've rebound Ellipsis.
Exactly. Thinking some more about it, perhaps the confusion would be sufficiently reduced if the repr of '...' would be 'Ellipsis (...)', and use this repr to appear in error messages rather than simply the name Ellipsis.
On Mon, 2021-05-31 at 11:37 -0300, André Roberge wrote:
In Python `...` is referred to as `Ellipsis` and cannot be assigned to. Yet, one can assign any value to the name `Ellipsis`.
Consider the following:
```
... Ellipsis ... == Ellipsis True Ellipsis Ellipsis Ellipsis = 3 Ellipsis 3 ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis # But I just did assign a new value to the name Ellipsis above. Ellipsis 3 ... Ellipsis ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
_______________________________________________ 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/NE2FAW... Code of Conduct: http://python.org/psf/codeofconduct/
Andre, did you have an experience where something related to Ellipsis/... confused you? It is not clear to me what exactly prompted you to single out Ellipsis (or it’s repr()?) On Mon, May 31, 2021 at 08:37 André Roberge <andre.roberge@gmail.com> wrote:
On Mon, May 31, 2021 at 12:20 PM MRAB <python@mrabarnett.plus.com> wrote:
On 2021-05-31 15:55, Paul Bryan wrote:
If you're proposing prevention of monkey patching Ellipsis, I think you'll have to go all-in on all builtins.
For example:
str = int
str
<class 'int'>
str == int
True
If you rebind str to int, the repr of str will say <class 'int'>, so you can tell that something's happened, but the repr of ... is always 'Ellipsis', even though you've rebound Ellipsis.
Exactly.
Thinking some more about it, perhaps the confusion would be sufficiently reduced if the repr of '...' would be 'Ellipsis (...)', and use this repr to appear in error messages rather than simply the name Ellipsis.
On Mon, 2021-05-31 at 11:37 -0300, André Roberge wrote:
In Python `...` is referred to as `Ellipsis` and cannot be assigned to. Yet, one can assign any value to the name `Ellipsis`.
Consider the following:
```
> ... Ellipsis > ... == Ellipsis True > Ellipsis Ellipsis > Ellipsis = 3 > Ellipsis 3 > ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis > # But I just did assign a new value to the name Ellipsis above. > Ellipsis 3 > ... Ellipsis > ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
_______________________________________________ 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/NE2FAW... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ 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/DIRDIQ... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido (mobile)
On Mon, May 31, 2021 at 2:40 PM Guido van Rossum <guido@python.org> wrote:
Andre, did you have an experience where something related to Ellipsis/... confused you? It is not clear to me what exactly prompted you to single out Ellipsis (or it’s repr()?)
Guido, the reason why I tried is that I am working on a project called friendly (previously named friendly-traceback) which aims to provide "easy to understand" explanations to beginners when they encounter tracebacks.[1] In playing with different cases involving assignments to a constant (__debug__, None, True, False, ... and Ellipsis as '...'), I came across this particular case which I thought was confusing: Python says that we cannot assign to Ellipsis ... and yet we can. I thought that the explanation provided by cPython itself could be made a bit clearer. The specific suggestion I made is based on the explanation *friendly* currently gives, where it specifies that Ellipsis refers to (...). Admittedly, this is rather a corner case. André ==== With friendly, I usually strive to cover more typical cases that are encountered by beginners, such as one example I gave at this year's PyConUS Education summit where, given the following message: AttributeError: partially initialized module 'turtle' has no attribute 'forward' (most likely due to a circular import) friendly adds the following "hint": Did you give your program the same name as a Python module? And, upon being prompted, friendly adds the following: I suspect that you used the name turtle.py for your program and that you also wanted to import a module with the same name from Python's standard library. If so, you should use a different name for your program. (This particular turtle is not hard-coded in friendly; any circular import is similarly analyzed and some further explanation is provided.) [1] Currently, I have at least 150 different cases yielding SyntaxErrors for which friendly can provide help (see https://aroberge.github.io/friendly-traceback-docs/docs/html/syntax_tracebac... for cases covered by unit tests) and probably a hundred or so of various types of other errors. Furthermore, friendly is designed so that the explanations can be translated into other languages; currently, every case friendly covers has explanations available in both English and French.
On Mon, May 31, 2021 at 08:37 André Roberge <andre.roberge@gmail.com> wrote:
On Mon, May 31, 2021 at 12:20 PM MRAB <python@mrabarnett.plus.com> wrote:
On 2021-05-31 15:55, Paul Bryan wrote:
If you're proposing prevention of monkey patching Ellipsis, I think you'll have to go all-in on all builtins.
For example:
> str = int
> str
<class 'int'>
> str == int
True
If you rebind str to int, the repr of str will say <class 'int'>, so you can tell that something's happened, but the repr of ... is always 'Ellipsis', even though you've rebound Ellipsis.
Exactly.
Thinking some more about it, perhaps the confusion would be sufficiently reduced if the repr of '...' would be 'Ellipsis (...)', and use this repr to appear in error messages rather than simply the name Ellipsis.
On Mon, 2021-05-31 at 11:37 -0300, André Roberge wrote:
In Python `...` is referred to as `Ellipsis` and cannot be assigned
to.
Yet, one can assign any value to the name `Ellipsis`.
Consider the following:
```
>> ... Ellipsis >> ... == Ellipsis True >> Ellipsis Ellipsis >> Ellipsis = 3 >> Ellipsis 3 >> ... = 4 File "<stdin>", line 1 ... = 4 ^ SyntaxError: cannot assign to Ellipsis >> # But I just did assign a new value to the name Ellipsis above. >> Ellipsis 3 >> ... Ellipsis >> ... == Ellipsis False
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
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/NE2FAW... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ 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/DIRDIQ... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido (mobile)
On Mon, May 31, 2021 at 12:36:34PM -0300, André Roberge wrote:
Thinking some more about it, perhaps the confusion would be sufficiently reduced if the repr of '...' would be 'Ellipsis (...)', and use this repr to appear in error messages rather than simply the name Ellipsis.
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. >>> type(4) <class 'int'> >>> int = list >>> type(4) <class 'int'> >>> int('123') ['1', '2', '3'] Objects are not their name, and their name is not the object. Objects do not know the name or names they are bound to. `...` is not a name, it is a syntactic symbol that is hard coded in the interpreter to the object which we popularly call "Ellipsis". You can't assign to the symbol any more than you can assign to the symbol `+`. On the other hand, `Ellipsis` is just a name. Like nearly all names in Python, you can rebind it or delete it. Rebinding the name doesn't affect the object `...`. It still knows itself as Ellipsis, no matter what names happen to be bound to it in some namespace or another. (Analogy: you would probably still think of yourself as André even if we all started to call you Bruce.) We *could* single out Ellipsis for special treatment, like None, True and False, but what's so special about Ellipsis that we should bother? The bottom line here is that the *name* "Ellipsis" is not special. It's just a name, like int, TypeError, and all the rest. If you want to make Ellipsis a keyword, like None, True and False, you would need some good reason for it. -- Steve
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. -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.
On Mon, May 31, 2021 at 9:12 PM David Mertz <mertz@gnosis.cx> wrote:
foo = "bar"
eval(repr(foo)) == eval(repr(eval(repr(foo)))) True
eval(repr(None)) == eval(repr(eval(repr(None)))) True
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.
repr(...) ...[Ellipsis]
...(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.
Oh... just in case I wasn't clear, `Ellipsis.__repr__()` would obviously need to be changed slightly as well along with adding .__call__() or .__getitem__() for this to work. -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.
On Mon, May 31, 2021 at 09:12:42PM -0400, David Mertz wrote:
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: [...] 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.
It's pretty standard behaviour for Python. >>> err = ValueError('something went wrong') >>> ValueError = list >>> eval(repr(err)) ['s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', ' ', 'w', 'e', 'n', 't', ' ', 'w', 'r', 'o', 'n', 'g'] The repr of an object tells you what the object thinks it is called; but `eval` evaluates the given source code according to whatever name bindings happen to exist at the time, which can shadow or monkey-patch the names that were used to generate the object in the first place. >>> eval(repr(NotImplemented)) NotImplemented >>> NotImplemented = len >>> eval(repr(str.__lt__('', None))) <built-in function len> The lesson here is not to rebind names if you don't want eval to use the rebound names :-) Right now, `eval(repr(...))` works unless you have shadowed the name Ellipsis. If we make the proposed changed, it will call whatever arbitrary object was bound to Ellipsis, so the best you can hope for is a TypeError: >>> eval('Ellipsis (...)') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: 'ellipsis' object is not callable Unless we make the ellipsis object `...` callable. But that doesn't help us if the name Ellipsis has been rebound. Then it will call the rebound object. I have to emphasise that this is standard, normal behaviour, and I still don't know why we are disturbed by Ellipsis behaving like nearly everything else in Python. The only oddity is that unlike most things, Ellipsis also has a special symbol `...` that most objects don't have. [...]
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.
"Errors should never pass silently." class Ellipse(Shape): ... myshape = Ellipsis(mysquare) # oops # much later on... myshape.draw() # TypeError Okay, it's a bit of a contrived set of circumstances, but it demonstrates the idea that functions should not ignore their arguments. Exceptions should, if possible, occur as close as possible to the actual error (the use of Ellipsis instead of Ellipse). If the parameter to a function has no effect, it shouldn't be a parameter. If you pass an invalid argument to the (hypothetical) callable Ellipsis, it should raise TypeError immediately, not ignore the argument. So we're trying to fix an issue of next to no practical importance, that doesn't really affect anyone, by building in more complexity and weird corner cases in the language. I don't think that's a good trade off. Shadowing and monkey-patching are advanced techniques, and we shouldn't demand the language protect newbies who accidentally shadow the built-in Ellipsis and then try to use eval. Not every builtin needs a mollyguard to protect against misuse. -- Steve
On Mon, May 31, 2021 at 11:41 PM Steven D'Aprano <steve@pearwood.info> wrote:
It's pretty standard behaviour for Python. Right now, `eval(repr(...))` works unless you have shadowed the name Ellipsis.
>>> err = ValueError('something went wrong') >>> ValueError = list >>> eval(repr(err)) ['s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', ' ', 'w', 'e', 'n', 't', ' ', 'w', 'r', 'o', 'n', 'g']
Yeah, my surprise was kind of a "thinko." I think I was thinking of the eval() separately from the repr(). But nonetheless, the idempotency question still arises, and I believe is reasonable.
Unless we make the ellipsis object `...` callable. But that doesn't help us if the name Ellipsis has been rebound. Then it will call the rebound object.
Let's change the behavior of the Ellipsis object slightly to have either a .__call__() or .__getitem__() method that returns itself
That was exactly what I suggested. The three dots themselves, which CANNOT be bound to any other object, could be callable or indexable. If you define a class Ellipsis to use that name, it makes no difference to `repr(...) == "...[Ellipsis]"` Note that I am NOT proposing `Ellipsis(...)` as the repr for EXACTLY that reason.
Not every builtin needs a mollyguard to protect against misuse.
I'm not likely to rebind `Ellipsis` so that's not really my concern. Rather, I'm interested in the point André Roberge started the thread with. The repr of '...' should be more self-explanatory to beginners. It's basically co-opting the square brackets or parenthesis to mean something that doesn't really have anything to do with calling or indexing in order to have a repr—in tracebacks specifically, but elsewhere also—that reminds users of the connection between `...` and `Ellipsis`. -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.
On Tue, Jun 1, 2021 at 1:46 AM David Mertz <mertz@gnosis.cx> wrote:
On Mon, May 31, 2021 at 11:41 PM Steven D'Aprano <steve@pearwood.info> wrote:
Not every builtin needs a mollyguard to protect against misuse.
I'm not likely to rebind `Ellipsis` so that's not really my concern. Rather, I'm interested in the point André Roberge started the thread with.
Actually, the very first observation I made is that, if you try to assign a value to '...', the traceback includes the message: SyntaxError: cannot assign to Ellipsis which is clearly wrong. If it would state: SyntaxError: cannot assign to '...' the only inconsistency left would be a more minor one, that is of the repr of '...' stating that it is Ellipsis which can be incorrect if Ellipsis is bound to a different value. Sorry for opening what became a rabbit hole of a discussion. André
The repr of '...' should be more self-explanatory to beginners. It's basically co-opting the square brackets or parenthesis to mean something that doesn't really have anything to do with calling or indexing in order to have a repr—in tracebacks specifically, but elsewhere also—that reminds users of the connection between `...` and `Ellipsis`.
-- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions. _______________________________________________ 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/USE2IC... Code of Conduct: http://python.org/psf/codeofconduct/
On Tue, Jun 01, 2021 at 05:48:34AM -0300, André Roberge wrote:
Actually, the very first observation I made is that, if you try to assign a value to '...', the traceback includes the message:
SyntaxError: cannot assign to Ellipsis
which is clearly wrong.
It is not _clearly_ wrong. Ellipsis is the name of the `...` symbol. Regardless of the state of the built-in name Ellipsis, whether it has been shadowed or monkey-patched, the symbol is still called Ellipsis. You would have to grossly misread or misinterpret the traceback: ... = 42 ^ SyntaxError: cannot assign to Ellipsis as referring to the *name* Ellipsis rather than the symbol as shown. So I would say its not wrong at all: it is technically and pedantically correct, which is the best kind of correct. So it is not *wrong*, but it does require a moderately subtle understanding of Python symbols, names, and values (objects). One easy change would be to just drop the capital E and call it "ellipsis" (without the quotes), or even "the ellipsis symbol". To my mind, that makes it clear we're talking about the symbol, not the builtin name. I dislike these: SyntaxError: cannot assign to '...' SyntaxError: cannot assign to ... I'm not assigning to the string '...'; the second one looks like the error message has been partially elided. So both are just as problematic as the error message we are trying to improve. [...]
the only inconsistency left would be a more minor one, that is of the repr of '...' stating that it is Ellipsis which can be incorrect if Ellipsis is bound to a different value.
And that I don't think we should bother changing. It is completely normal for the names of certain classes, functions and other values to refer to the original name rather than the shadowing name. Ellipsis is just another one of them. -- Steve
We have the following. >>> 12 = True SyntaxError: can't assign to literal >>> True = False SyntaxError: can't assign to keyword >>> ... = False SyntaxError: can't assign to Ellipsis We also have (works better in monospaced font) >>> d[] = True d[] = True ^ SyntaxError: invalid syntax Beginners might appreciate having instead as error messages: SyntaxError: can't assign to literal: 12 SyntaxError: can't assign to keyword: True SyntaxError: can't assign to literal: ... -- Jonathan
On Tue, Jun 01, 2021 at 08:28:56PM +1000, Steven D'Aprano wrote:
One easy change would be to just drop the capital E and call it "ellipsis" (without the quotes), or even "the ellipsis symbol". To my mind, that makes it clear we're talking about the symbol, not the builtin name.
https://bugs.python.org/issue44278 Thanks Serhiy! -- Steve
One other note that I'm surprised hasn't been brought up: In another thread, there is a discussion about what to use as sentinel objects -- often to indicate non-specified parameters, when None is a valid value. A number of people have proposed using the ellipses as such a value, as it already exists, is built in, is a singleton, has only specialized uses at the moment in different contexts, and is a good mnemonic for "missing". Apparently a number of people already use it that way. If Ellipses that does become a standard recommend sentinel object -- that might be a motivator for making it a special word, like None. However, I"m still a bit confused as to why the rep of the ellipses object isn't it's literal already. Is there any other example of this? In [1]: repr(list()) Out[1]: '[]' In [2]: repr(dict()) Out[2]: '{}' Hmm -- there is set: In [3]: repr(set()) Out[3]: 'set()' which breaks eval if you rebind it. Though it doesn't use the name if it's not empty: In [16]: s = {1,2,3} In [17]: repr(s) Out[17]: '{1, 2, 3}' In the end, I think this is an argument for not using ellipses as a standard sentinel, rather than an argument for making "Ellipses" more special. -CHB On Tue, Jun 1, 2021 at 4:33 AM Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, Jun 01, 2021 at 08:28:56PM +1000, Steven D'Aprano wrote:
One easy change would be to just drop the capital E and call it "ellipsis" (without the quotes), or even "the ellipsis symbol". To my mind, that makes it clear we're talking about the symbol, not the builtin name.
https://bugs.python.org/issue44278
Thanks Serhiy!
-- Steve _______________________________________________ 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/MRCYKQ... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
31.05.21 17:37, André Roberge пише:
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
Making Ellipsis a keyword will break ast.Ellipsis (and maybe some third-party libraries).
On Mon, May 31, 2021 at 4:17 PM Serhiy Storchaka <storchaka@gmail.com> wrote:
31.05.21 17:37, André Roberge пише:
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
Making Ellipsis a keyword will break ast.Ellipsis (and maybe some third-party libraries).
I realized that after my initial post which is why I subsequently suggested that its repr should perhaps be "Ellipsis (...)". But, I admit, it is a rather obscure corner case that few, if any beginners would encounter and be confused by the error message.
_______________________________________________ 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/4K47SC... Code of Conduct: http://python.org/psf/codeofconduct/
I think making 'Ellipsis' a reserved word is too much. The analogy with non-reserved words like `int`, `str`, `map`, `print`, and so on, illustrate this, I think. I.e. redefining those is likely to cause bad things to happen, but we're consenting adults, and in the end they are just names. However, I think improving the repr() of the Ellipsis object itself to remind users of the connection with its special literal `...` is a great idea. On Mon, May 31, 2021 at 3:27 PM André Roberge <andre.roberge@gmail.com> wrote:
On Mon, May 31, 2021 at 4:17 PM Serhiy Storchaka <storchaka@gmail.com> wrote:
31.05.21 17:37, André Roberge пише:
For consistency, `Ellipsis` (the name) should **always** refer to the same object that `...` refers to, so that both could not be assigned a new value.
Making Ellipsis a keyword will break ast.Ellipsis (and maybe some third-party libraries).
I realized that after my initial post which is why I subsequently suggested that its repr should perhaps be "Ellipsis (...)". But, I admit, it is a rather obscure corner case that few, if any beginners would encounter and be confused by the error message.
_______________________________________________ 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/4K47SC... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ 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/KYIOVH... Code of Conduct: http://python.org/psf/codeofconduct/
-- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.
On Tue, Jun 1, 2021 at 5:40 AM David Mertz <mertz@gnosis.cx> wrote:
I think making 'Ellipsis' a reserved word is too much. The analogy with non-reserved words like `int`, `str`, `map`, `print`, and so on, illustrate this, I think. I.e. redefining those is likely to cause bad things to happen, but we're consenting adults, and in the end they are just names.
However, I think improving the repr() of the Ellipsis object itself to remind users of the connection with its special literal `...` is a great idea.
Originally, the notation "..." could only be used inside a subscript, and anywhere else, you'd have to spell it "Ellipsis". Now that you can use "..." anywhere, would it be worth switching the repr to just be that? ChrisA
+1 On Tue, 2021-06-01 at 05:46 +1000, Chris Angelico wrote:
On Tue, Jun 1, 2021 at 5:40 AM David Mertz <mertz@gnosis.cx> wrote:
I think making 'Ellipsis' a reserved word is too much. The analogy with non-reserved words like `int`, `str`, `map`, `print`, and so on, illustrate this, I think. I.e. redefining those is likely to cause bad things to happen, but we're consenting adults, and in the end they are just names.
However, I think improving the repr() of the Ellipsis object itself to remind users of the connection with its special literal `...` is a great idea.
Originally, the notation "..." could only be used inside a subscript, and anywhere else, you'd have to spell it "Ellipsis". Now that you can use "..." anywhere, would it be worth switching the repr to just be that?
ChrisA _______________________________________________ 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/EK7DPA... Code of Conduct: http://python.org/psf/codeofconduct/
31.05.21 22:46, Chris Angelico пише:
Originally, the notation "..." could only be used inside a subscript, and anywhere else, you'd have to spell it "Ellipsis". Now that you can use "..." anywhere, would it be worth switching the repr to just be that?
How would you then distinguish a recursive list from a list containing Ellipsis?
a = []; a.append(a); a [[...]] [[...]] [[Ellipsis]]
On Tue, Jun 1, 2021 at 6:22 AM Serhiy Storchaka <storchaka@gmail.com> wrote:
31.05.21 22:46, Chris Angelico пише:
Originally, the notation "..." could only be used inside a subscript, and anywhere else, you'd have to spell it "Ellipsis". Now that you can use "..." anywhere, would it be worth switching the repr to just be that?
How would you then distinguish a recursive list from a list containing Ellipsis?
a = []; a.append(a); a [[...]] [[...]] [[Ellipsis]]
Good point, didn't think of that. Although... since that's an arbitrary placeholder, it could be changed to pretty much anything. Maybe <...> or something? The current repr may not technically be ambiguous, but it will silently do the wrong thing if you try to eval it. You can even ast.literal_eval(repr(a)) and it'll appear to work. Not a huge deal whichever way, though. The token "..." is used in a variety of non-ellipsis ways, such as doctest, and that isn't inherently a problem. ChrisA
31.05.21 23:28, Chris Angelico пише:
Although... since that's an arbitrary placeholder, it could be changed to pretty much anything. Maybe <...> or something? The current repr may not technically be ambiguous, but it will silently do the wrong thing if you try to eval it. You can even ast.literal_eval(repr(a)) and it'll appear to work.
It was already discussed in 2015 [1], but the idea of <...> was rejected by Guido [2]. [1] https://mail.python.org/archives/list/python-ideas@python.org/thread/T2T7WR5... [2] https://mail.python.org/archives/list/python-ideas@python.org/thread/RAZMTY2...
On 2021-05-31 21:19, Serhiy Storchaka wrote:
31.05.21 22:46, Chris Angelico пише:
Originally, the notation "..." could only be used inside a subscript, and anywhere else, you'd have to spell it "Ellipsis". Now that you can use "..." anywhere, would it be worth switching the repr to just be that?
How would you then distinguish a recursive list from a list containing Ellipsis?
>>> a = []; a.append(a); a [[...]] >>> [[...]] [[Ellipsis]]
Why is it 3 dots anyway? As we've already ascribed a meaning to 3 dots, why not use 4 dots in this use?
On Mon, May 31, 2021 at 10:55:08PM +0100, MRAB wrote:
a = []; a.append(a); a [[...]] [[...]] [[Ellipsis]]
Why is it 3 dots anyway? As we've already ascribed a meaning to 3 dots, why not use 4 dots in this use?
Three dots for ommitted text is standard in English. Four dots is an ellipsis followed by a full stop. We could go against that convention (Python is not English, although it is based closely on many English conventions) but honestly I think that any change in this area is of such little benefit that it's not worth the potential disruption to documentation and doctests. -- Steve
On 2021-05-31 12:46, Chris Angelico wrote:
On Tue, Jun 1, 2021 at 5:40 AM David Mertz <mertz@gnosis.cx> wrote:
I think making 'Ellipsis' a reserved word is too much. The analogy with non-reserved words like `int`, `str`, `map`, `print`, and so on, illustrate this, I think. I.e. redefining those is likely to cause bad things to happen, but we're consenting adults, and in the end they are just names.
However, I think improving the repr() of the Ellipsis object itself to remind users of the connection with its special literal `...` is a great idea.
Originally, the notation "..." could only be used inside a subscript, and anywhere else, you'd have to spell it "Ellipsis". Now that you can use "..." anywhere, would it be worth switching the repr to just be that?
I feel like that might be confusing. We do have things like lists where the repr of an empty list is [], but lists are pretty basic and ubiquitous Python objects that people usually learn about quite early. Ellipsis is a more obscure thing so it seems worthwhile to label it somehow rather than just giving a cryptic three dots. -- Brendan Barnwell "Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail." --author unknown
El lun, 31 may 2021 a las 12:40, David Mertz (<mertz@gnosis.cx>) escribió:
I think making 'Ellipsis' a reserved word is too much. The analogy with non-reserved words like `int`, `str`, `map`, `print`, and so on, illustrate this, I think. I.e. redefining those is likely to cause bad things to happen, but we're consenting adults, and in the end they are just names.
However, I think improving the repr() of the Ellipsis object itself to remind users of the connection with its special literal `...` is a great idea.
Why isn't `repr(...)` just `...`?
31.05.21 22:24, André Roberge пише:
On Mon, May 31, 2021 at 4:17 PM Serhiy Storchaka <storchaka@gmail.com <mailto:storchaka@gmail.com>> wrote: 31.05.21 17:37, André Roberge пише: > For consistency, `Ellipsis` (the name) should **always** refer to the > same object that `...` refers to, so that both could not be assigned a > new value.
Making Ellipsis a keyword will break ast.Ellipsis (and maybe some third-party libraries).
I realized that after my initial post which is why I subsequently suggested that its repr should perhaps be "Ellipsis (...)".
It does not help. If Ellipsis is a keyword, it is not possible to have ast.Ellipsis. Not mentioned that it would be pretty confusing by itself -- why you need to write Ellipsis(), but not None() or True()?
participants (14)
-
André Roberge
-
Brendan Barnwell
-
Chris Angelico
-
Christopher Barker
-
David Mertz
-
Filipe Laíns
-
Guido van Rossum
-
Jelle Zijlstra
-
Jonathan Fine
-
MRAB
-
Paul Bryan
-
Serhiy Storchaka
-
Simão Afonso
-
Steven D'Aprano