Notation for subscripts.
Dear Developers, Given a subscriptable object s, the intended rule for the notation for getting an item of s seems that, for any expression {e}, such as "x, ", s[{e}] (i.e., s[x, ] if {e} is "x, ") means the same as s[({e})] (i.e., s[(x, )] in the considered case), namely, should be evaluated as s.__getitem__(({e})) (or s.__class_getitem__(({e})) when that applies). If this is the rule, then it looks simple and hence friendly to the user. However, there are at least two exceptions: (1) The case where {e} is the empty expression "": The expression s[] raises SyntaxError instead of being evaluated in the same way as s[()] is. (2) The case where {e} contains "*" for unpacking: An expression containing the unpacking notation, such as s[*iterable, ] raises SyntaxError instead of being evaluated in the same way as s[(*iterable, )] in this example, is. Are these (and other if any) exceptions justified? If not, I propose having the described rule to have full effect if that would simplify the syntax. This would affect currently working codes which rely on SyntaxError raised in either of the described ways (through eval, exec or import??). I wonder if reliance on SyntaxError in these cases should be supported in all future versions of Python. Best regards, Takuo Matsuoka
On 2021-08-13 at 23:18:29 +1100, Matsuoka Takuo <motogeomtop@gmail.com> wrote:
Given a subscriptable object s, the intended rule for the notation for getting an item of s seems that, for any expression {e}, such as "x, ", s[{e}] (i.e., s[x, ] if {e} is "x, ") means the same as s[({e})]
If e is an expression, then s[e] means s[e]. Sometimes, e happens to be a tuple, but Python doesn't create a tuple just to call __getitem__. The following expression: x, is a tuple all by itself. Also: (x,) is that same tuple.
(i.e., s[(x, )] in the considered case), namely, should be evaluated as s.__getitem__(({e})) (or s.__class_getitem__(({e})) when that applies). If this is the rule, then it looks simple and hence friendly to the user. However, there are at least two exceptions:
(1) The case where {e} is the empty expression "":
There is no such thing as an "empty expression." "" is a string containing no characters.
The expression s[] raises SyntaxError ...
Because there is no expression (which is different from a hypothetical "empty expression."
... instead of being evaluated in the same way as s[()] is.
() is a tuple with no elements, just as [] is a list with no elements, and "" is a string with no elements.
Thanks 2QdxY4RzWzUUiLuE for your thoughtful response. I shouldn't have used the word "expression" since it was going to be taken as a Python term. Let me clarify the issue. An optional starred expression (denoted "[starred_expression]" in the specification of the syntax) is a natural generalization of an expression list (which is not necessarily an expression in the Python sense) in the sense that use of the latter as a special case of the former will lead to intuitively expected results at all places where the former is allowed. The issue is these two things seem to be treated unnecessarily differently. Namely, the syntax requires an expression list at some places (not even optionally), but does not allow an optional starred expression at the same places. In such a place, one must turn an optional starred expression into an expression (in the Python sense) by putting parentheses around it while parentheses around an expression list are optional. This difference in treatment seemed unintuitive to me at least inside brackets. This means non-experts like me may need to take extra care to stay safe under possibility of confusion at those places. Must most non-experts be happy with this in your assessment? A solution would be simply not to exclude optional starred expressions where an expression list is required now (since it may be too late now to require a single expression at those places if that could be better). Best regards, Takuo
Matsuoka Takuo writes:
Let me clarify the issue. An optional starred expression (denoted "[starred_expression]" in the specification of the syntax) is a natural generalization of an expression list (which is not necessarily an expression in the Python sense) in the sense that use of the latter as a special case of the former will lead to intuitively expected
I would not have expected that at all, as *(1,2) is macro-like syntax that expands to an "unboxed" sequence of objects (and must do so, to serve its purpose of being "spliced into" a sequence being constructed), while 1,2 is expression syntax that is evaluated to a single object (which happens to be a sequence of objects "boxed up" in a tuple), and the parentheses may be omitted if the only possible interpretation is "tuple of all comma-separated objects". But for *(1,2), it could be that, but because it is "unboxed", it could also be "list of all comma-separated objects". Again, it is *not* a macro, substituting the text "1, 2" for the text "*(1,2)", expanding any newly added *-constructs recursively, and finally the constructor is executed on the resulting text. Like everything else in Python, it is executed on objects. What's unique about it is that it produces them "unboxed", ready for splicing (or inversely collecting a slice, in the case of a *-ed assignment target). Now, that's not the Language Reference (at least, I didn't consult it!), that's my intuition about *-constructs. But as far as I can tell it accounts for all their behavior, including this SyntaxError. Steve
Dear Steve, Thank you for your thoughts. To be precise, the sequence of letters "*(1,2)" is not actually a "starred expression" in the sense of the Python Language, but e.g., "*(1,2), " is. (A comma is trailing.) Please check the definitions here: https://docs.python.org/3/reference/expressions.html#expression-lists For instance, "(*(1,2) )" raises SyntaxError. Now, is "1,2," more boxed up than "*(1,2)," is? The *current* rule surely says the former is a tuple at some places and the latter is not, but otherwise, I don't see any parenthesis nor bracket around "1,2,". May more parentheses than brackets visible there? I see commas in both, so that's not the difference. Is there no way "*(1,2)," could equally be boxed up at exactly the same places where "1,2," can? Importantly, what problem may be caused by this in practice, or from what problem does SyntaxError currently raised there save us? For instance, if someone writes "s[*(1,2),]" in fact wanting "s[ [*(1,2),] ]" but forgets to box up "*(1,2),", then the same thing can happen for "s[ [1,2,] ]" (i.e., it can be mistyped as "s[1,2,]" but without SyntaxError this time). It would at least be consistent if we got SyntaxError in both cases (namely, the syntax allowed only a single Python expression here), but if we don't want SyntaxError in the latter case, how may we want it in the former case? By the way, please note I wish "*(1,2)," to be treated like "1,2," only where the current syntax expects an expression list. Elsewhere, I don't mind it if starred expressions remain treated as unboxed or whatever. Best regards, Takuo
Have you seen PEP 637? IIRC it has discussions on a[] and a[*x]. Note that it was rejected, but the idea of a[*x] is being resurrected for PEP 646. On Fri, Aug 13, 2021 at 5:43 AM Matsuoka Takuo <motogeomtop@gmail.com> wrote:
Dear Developers,
Given a subscriptable object s, the intended rule for the notation for getting an item of s seems that, for any expression {e}, such as "x, ", s[{e}] (i.e., s[x, ] if {e} is "x, ") means the same as s[({e})] (i.e., s[(x, )] in the considered case), namely, should be evaluated as s.__getitem__(({e})) (or s.__class_getitem__(({e})) when that applies). If this is the rule, then it looks simple and hence friendly to the user. However, there are at least two exceptions:
(1) The case where {e} is the empty expression "": The expression s[] raises SyntaxError instead of being evaluated in the same way as s[()] is.
(2) The case where {e} contains "*" for unpacking: An expression containing the unpacking notation, such as s[*iterable, ] raises SyntaxError instead of being evaluated in the same way as s[(*iterable, )] in this example, is.
Are these (and other if any) exceptions justified? If not, I propose having the described rule to have full effect if that would simplify the syntax. This would affect currently working codes which rely on SyntaxError raised in either of the described ways (through eval, exec or import??). I wonder if reliance on SyntaxError in these cases should be supported in all future versions of Python.
Best regards, Takuo Matsuoka _______________________________________________ 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/V2WFMN... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Matsuoka Takuo writes:
I don't see any parenthesis nor bracket around "1,2,".
Parentheses are not part of tuple display syntax, with the exception of "()", the empty tuple. Parenthesis are needed for tuple displays only to group the display in the context of a larger expression. This is my point about "*" not being a macro in the sense of m4 or Tex: the fact that the expression that in text is "*x" expands to something that in text we express as "y, z," doesn't mean they are the same thing as tuples in Python, even though we express the tuple in exactly the same text. In fact, when we write "y, z," *in a Python program* we are instructing Python to construct a *single tuple object*, but in my model of "*x", it does not construct an object *at all*: >>> *(1,2) File "<stdin>", line 1 SyntaxError: can't use starred expression here It is an expression that denotes a directive to a sequence constructor to "take objects from x and add them to the sequence". As I wrote before, I don't know if this model is how Python actually works, but it accounts for *all* of the behavior I've ever seen from starred expressions, including errors.
I see commas in both, so that's not the difference. Is there no way "*(1,2)," could equally be boxed up at exactly the same places where "1,2," can?
There's no "*" in "1,2," so it can play a different role from "*(1,2,)". I think it's useful that it does. Why do you think it's a good idea that *(1,2)* sometimes constructs an object, and other times does something wildly different?
Importantly, what problem may be caused by this in practice,
I'd have to change my model of what it does, or probably add an annoying special case "if a starred expression occurs in a context where its intended meaning is nonsense, and an actual tuple would do exactly the right thing, go ahead, pretend there's tuple syntax there, and box it up." My intuition is no more valuable than yours, but I think you have to admit that yours is the special case given what starred expressions are *needed* for, and so you admit I have the Zen on my side (for what that's worth).
or from what problem does SyntaxError currently raised there save us? For instance, if someone writes "s[*(1,2),]" in fact wanting "s[ [*(1,2),] ]" but forgets to box up "*(1,2),", then the same thing can happen for "s[ [1,2,] ]"
But these errors are exactly what you want to train people to expect to work! Every time I get syntax errors as above, my model is reinforced. If I don't get them, my model becomes more fragile and I'm *more* prone to such errors, because I start to believe that "*(1,2)" creates the tuple "(1,2)".
(i.e., it can be mistyped as "s[1,2,]" but without SyntaxError this time). It would at least be consistent if we got SyntaxError in both cases (namely, the syntax allowed only a single Python expression here), but if we don't want SyntaxError in the latter case, how may we want it in the former case?
I defy you to explain how the compiler or interpreter can distinguish any of those stipulated programmer errors from intended programs.
By the way, please note I wish "*(1,2)," to be treated like "1,2," only where the current syntax expects an expression list.
I think you're still thinking that "*" is an m4 macro, and it just isn't. Steve
I believe this is useful since this syntax is developed in some libraries as an internal DSL. At least I have seen it in pandas, a library handling tables. df[(df['a'] < df['b']) & (df['b'] < df['c'])] df[~df['a'].isin(df['b'])] df[df['b'].isin(df['a']) & (df['c'] < df['d'])] More examples in {[pandas-doc-url]/user_guide/indexing.html}. On 13/08/2021 20:18, Matsuoka Takuo wrote:
Dear Developers,
Given a subscriptable object s, the intended rule for the notation for getting an item of s seems that, for any expression {e}, such as "x, ", s[{e}] (i.e., s[x, ] if {e} is "x, ") means the same as s[({e})] (i.e., s[(x, )] in the considered case), namely, should be evaluated as s.__getitem__(({e})) (or s.__class_getitem__(({e})) when that applies). If this is the rule, then it looks simple and hence friendly to the user. However, there are at least two exceptions:
(1) The case where {e} is the empty expression "": The expression s[] raises SyntaxError instead of being evaluated in the same way as s[()] is.
(2) The case where {e} contains "*" for unpacking: An expression containing the unpacking notation, such as s[*iterable, ] raises SyntaxError instead of being evaluated in the same way as s[(*iterable, )] in this example, is.
Are these (and other if any) exceptions justified? If not, I propose having the described rule to have full effect if that would simplify the syntax. This would affect currently working codes which rely on SyntaxError raised in either of the described ways (through eval, exec or import??). I wonder if reliance on SyntaxError in these cases should be supported in all future versions of Python.
Best regards, Takuo Matsuoka _______________________________________________ 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/V2WFMN... Code of Conduct: http://python.org/psf/codeofconduct/
Matsuoka Takuo <motogeomtop@gmail.com>:
Now, is "1,2," more boxed up than "*(1,2)," is? The *current* rule surely says the former is a tuple at some places and the latter is not,
Actually, this was wrong. First of all,
*(1,2), (1, 2)
Moreover, while the Language Reference says return_stmt ::= "return" [expression_list] at https://docs.python.org/3/reference/simple_stmts.html#the-return-statement things like return *(), are already allowed and () gets returned in this case, and so on! I haven't examined everything, but so far, subscription is the only place I've found where a starred expression in place of an expression list indeed raises SyntaxError. In particular, there really doesn't seem to be any reason why a starred expression should be rejected from any place where an expression list is accepted. In fact, rejection should _not_ be expected, it seems. My proposal at this point would be: (1) remove the definition of "expression_list" from the specification of the syntax (2) replace every occurrence of it in the specification with "starred_expression". At most places this seems to only recover the current behaviour. (Even if this idea does not survive in the end, I think the Language Reference should be fixed to describe the behaviour correctly. The actual behaviour is making better sense to me than what the Reference is describing now.) A minor question to be left then would be which new instance of "starred_expression" in the specification of the syntax may further be replaced with the optional one or "[starred_expression]", e.g., whether s[] would be better allowed and evaluated to s.__getitem__(()). This may be complicated. For example, I'm already used to returning None with return and so on. Even then, s[] doesn't seem very bad to me. Best regards, Takuo
Dear Guido van Rossum, Thank you for bringing the PEP's to my attention. The idea of PEP 637 on a[*x] is different from my idea. The PEP's idea appears making subscription analogous to function calls. In the end, a[*x] would have been equivalent to a[tuple(x)] if the PEP had been adopted. a[*x] in PEP 646 is similar, but has more restrictions on what formulas can fill the brackets. I understand only the a[*x] part of PEP 637 has been found of enough interest so far. For this part, 637 seems better than 646 in that it looks simpler. A concern about pursuing analogy with function calls may be there already is a difference, namely, a[x] and a[x,] are not equivalent while f(x) and f(x,) are. In particular, a[*(x, )] not being equivalent to a[x] might at least be confusing. On the other hand, my idea was just a slight change from the current syntax by simple two steps described in my previous post. In particular, a[*x] would remain invalid, but a[*x, ] would be valid and equivalent to a[tuple(x)] (just as *x, at certain places is equivalent to tuple(x) ). PEP 637 has proposed to leave a[] invalid, which in their scheme seems confusing to me since a[*()] would be valid (and equivalent to a[tuple(())] or a[()] ), as well as seems to go against the analogy to calling of functions: f() is valid, just not equivalent to f(()) . Best regards, Takuo 2021年8月16日(月) 10:58 Guido van Rossum <guido@python.org>:
Have you seen PEP 637? IIRC it has discussions on a[] and a[*x]. Note that it was rejected, but the idea of a[*x] is being resurrected for PEP 646.
On Fri, Aug 13, 2021 at 5:43 AM Matsuoka Takuo <motogeomtop@gmail.com> wrote:
Dear Developers,
Given a subscriptable object s, the intended rule for the notation for getting an item of s seems that, for any expression {e}, such as "x, ", s[{e}] (i.e., s[x, ] if {e} is "x, ") means the same as s[({e})] (i.e., s[(x, )] in the considered case), namely, should be evaluated as s.__getitem__(({e})) (or s.__class_getitem__(({e})) when that applies). If this is the rule, then it looks simple and hence friendly to the user. However, there are at least two exceptions:
(1) The case where {e} is the empty expression "": The expression s[] raises SyntaxError instead of being evaluated in the same way as s[()] is.
(2) The case where {e} contains "*" for unpacking: An expression containing the unpacking notation, such as s[*iterable, ] raises SyntaxError instead of being evaluated in the same way as s[(*iterable, )] in this example, is.
Are these (and other if any) exceptions justified? If not, I propose having the described rule to have full effect if that would simplify the syntax. This would affect currently working codes which rely on SyntaxError raised in either of the described ways (through eval, exec or import??). I wonder if reliance on SyntaxError in these cases should be supported in all future versions of Python.
Best regards, Takuo Matsuoka _______________________________________________ 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/V2WFMN... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido van Rossum (python.org/~guido) Pronouns: he/him (why is my pronoun here?)
Dear Steve, Thank you for your detailed explanation.
(i.e., it can be mistyped as "s[1,2,]" but without SyntaxError this time). It would at least be consistent if we got SyntaxError in both cases (namely, the syntax allowed only a single Python expression here), but if we don't want SyntaxError in the latter case, how may we want it in the former case?
I defy you to explain how the compiler or interpreter can distinguish any of those stipulated programmer errors from intended programs.
Sure, if you ever want any error raised in those cases, that's going to be SyntaxError to be always raised regardless of the programmer's intention. That's fine. But then if you don't want SyntaxError in the "latter" case, it in fact means you never want any error raised since SyntaxError is the only thing you could hope for anyway. So I could equivalently have asked "if we never want any error raised in the latter case, how may we want some error raised at least sometimes in the former case?". This may have been clearer to you, but it's an equivalent question. Anyway, I assume everything you say about "*(1,2)" is right, but it's not "*(1,2)" that I wanted to create an object, but, as I have indicated, it's things like "*iterable , " (with comma!), where the iterable may be "(1,2)". Just as in "1,2", the comma indicates the intention to create an object. For example,
*(1,2), (1, 2)
and another example:
*(), *(1,2) (1, 2)
I find it unfortunate SyntaxError you got with
*(1,2)
says "can't use starred expression here" since "*(1,2)" is not really a "starred expression" as defined in the Language Reference. I think this should be fixed, so have started a new thread on that, titled '''SyntaxError says: "can't use starred expression here", but its not the same "starred expression" defined in the Language Reference''', You are invited to comment on that! Best regards, Takuo
On Thu, Aug 19, 2021 at 11:27 PM Matsuoka Takuo <motogeomtop@gmail.com> wrote:
Dear Steve,
Thank you for your detailed explanation.
(i.e., it can be mistyped as "s[1,2,]" but without SyntaxError this time). It would at least be consistent if we got SyntaxError in both cases (namely, the syntax allowed only a single Python expression here), but if we don't want SyntaxError in the latter case, how may we want it in the former case?
I defy you to explain how the compiler or interpreter can distinguish any of those stipulated programmer errors from intended programs.
Sure, if you ever want any error raised in those cases, that's going to be SyntaxError to be always raised regardless of the programmer's intention. That's fine. But then if you don't want SyntaxError in the "latter" case, it in fact means you never want any error raised since SyntaxError is the only thing you could hope for anyway. So I could equivalently have asked "if we never want any error raised in the latter case, how may we want some error raised at least sometimes in the former case?". This may have been clearer to you, but it's an equivalent question.
Anyway, I assume everything you say about "*(1,2)" is right, but it's not "*(1,2)" that I wanted to create an object, but, as I have indicated, it's things like "*iterable , " (with comma!), where the iterable may be "(1,2)". Just as in "1,2", the comma indicates the intention to create an object. For example,
*(1,2), (1, 2)
and another example:
*(), *(1,2) (1, 2)
I find it unfortunate SyntaxError you got with
*(1,2)
says "can't use starred expression here" since "*(1,2)" is not really a "starred expression" as defined in the Language Reference. I think this should be fixed, so have started a new thread on that, titled '''SyntaxError says: "can't use starred expression here", but its not the same "starred expression" defined in the Language Reference''', You are invited to comment on that!
Is the issue just one of wording in the exception message, or are you asking for a change of functionality? In your final example, you've never said that you're creating a tuple, so it's correct to get a SyntaxError. I'm confused as to whether you're asking for this to have meaning, or if instead you are simply proposing a change to wording. Changes to wording can definitely be done, and aren't a major backward or forward compatibility concern. ChrisA
Matsuoka Takuo writes:
*(1,2), (1, 2)
Yes, this works, and now that I see you just want that to work in "a[*(1,2),]", I agree, I don't know why that is a syntax error. This works, of course: t = *(1,2), a[t] (in the sense that if a is a sequence you get a TypeError because the index isn't an integer or slice, but if it's a mapping you'll get the value corresponding to (1,2) or a KeyError because it's not in the mapping). I think it's not good that "a[*(1,2),]" gives a SyntaxError, but I don't know why it was made that way in the first place.
I find it unfortunate SyntaxError you got with
*(1,2)
says "can't use starred expression here" since "*(1,2)" is not really a "starred expression" as defined in the Language Reference.
I don't have time to go into that tonight but if the appropriate thread gets takeup I'll comment there. You could promote the issue by submitting a merge request. Steve
Dear ChrisA, Steve, Thank you for your comments. ChrisA, it was off the main topic, but for me, the issue was just one of wording in the exception message. It's good to hear changes to wording can be done without compatibility concerns. I'll find out about merge request suggested by Stephen J. Turnbull. Steve, I think care is necessary to decide whether the validity of
t = *(1,2), a[t]
suffices to justify the expression "a[*(1,2),]". It could only justify a[ (*(1,2),) ] Note for example,
s = (1,2) t = *s, [t] == [*s,] False
Another exmaple:
t = *s, f(t) == f(*s,) False
However, for an appropriate object "a", we have
t = *(1,2), a[t] == a[1,2] True
which must be a special thing. I think this should be compared with
t = *s, (t) == (*s,) True
(In the above, I constructed "a" (and "f") by
def f(*args, **kwargs): ... return locals() ... class A: ... @property ... def __getitem__(self): ... return f ... a = A()
) Here's another piece of similarity.
[1,] == [1] True f(1,) == f(1) True (1,) == (1) False a[1,] == a[1] False
Thank you for your suggestion to submit a merge request. Best regards, Takuo On Fri, 20 Aug 2021 at 01:33, Stephen J. Turnbull <turnbull.stephen.fw@u.tsukuba.ac.jp> wrote:
Matsuoka Takuo writes:
*(1,2), (1, 2)
Yes, this works, and now that I see you just want that to work in "a[*(1,2),]", I agree, I don't know why that is a syntax error. This works, of course:
t = *(1,2), a[t]
(in the sense that if a is a sequence you get a TypeError because the index isn't an integer or slice, but if it's a mapping you'll get the value corresponding to (1,2) or a KeyError because it's not in the mapping). I think it's not good that "a[*(1,2),]" gives a SyntaxError, but I don't know why it was made that way in the first place.
I find it unfortunate SyntaxError you got with
*(1,2)
says "can't use starred expression here" since "*(1,2)" is not really a "starred expression" as defined in the Language Reference.
I don't have time to go into that tonight but if the appropriate thread gets takeup I'll comment there. You could promote the issue by submitting a merge request.
Steve
Dear Developers, After some findings and further thoughts through this thread, I have formulated a proposal as follows. (I thank everyone who has commented in this thread). For the necessary definitions, please look at https://docs.python.org/3/reference/expressions.html#subscriptions https://docs.python.org/3/reference/expressions.html#expression-lists https://docs.python.org/3/reference/expressions.html#slicings Difference from PEP 646 will be explained in a remark to follow. Note: In view of the definition of an expression statement and that of an assignment statement https://docs.python.org/3/reference/simple_stmts.html#expression-statements https://docs.python.org/3/reference/simple_stmts.html#assignment-statements I believe the correct definition of a starred expression actually used is starred_expression ::= expression | (starred_item ",")+ [starred_item] (that is, use "+" instead of "*"). Issues treated -------------- (1) The Language Reference is currently not describing the actual treatment of starred expressions precisely. For instance, the Language Reference says return_stmt ::= "return" [expression_list] at https://docs.python.org/3/reference/simple_stmts.html#the-return-statement but things like return *x, *y are accepted, which makes good sense and should be an officially supported use I think, but is not documented (in the Language Reference at least). (2) The rules on subscription of an object is not as simple as it can be. For instance, things like "a[*x,]" or "a[]" raises SyntaxError possibly unexpectedly. Proposal -------- (Z) Correct the definition of a starred expression in the Language Reference. (A) Syntax ------ Simplify the syntax as described in the Language Reference in the following manner. (A1) Remove the definition of "expression_list". (A2) Then replace every occurrence of it in the specification of the syntax with "starred_expression". In particular, change the definition of subscription to subscription ::= primary "[" starred_expression "]" Semantics --------- Reduce the interpretation of resulting newly valid expressions and statements to that of previously valid ones in the obvious manner. That is, interpret them as if each of the starred expressions in place of an expression list were packed in parentheses just around it. (B) Syntax ------ Change the definition of subscription further to subscription ::= primary "[" [starred_expression] "]" (meaning a starred expression there is now optional). Semantics --------- For subscription, without changing the meaning of the previously valid expressions, make the pair "[", "]" and the pair "[(", ")]" interchangeable. That is, interpret the brackets "[" and "]" for subscription as if "[" is a shorthand for .__getitem__(( (or .__class_getitem__(( depending on the object in front of it) and "]" is a shorthand for )) at the time of evaluation, and similarly at assignment and deletion in the obvious appropriate way using the methods __setitem__ and __delitem__ respectively. (C) Syntax ------ Change the definition of a slicing to slicing ::= primary "[" [slice_expression] "]" slice_expression ::= slice_item | (starred_slice_item ",")+ [starred_slice_item] starred_slice_item ::= starred_item | slice_item Semantics --------- Reduce the interpretation of a slicing to that of a subscription in the usual way, namely, by replacing every item between the brackets which is a proper slice with an expression for the corresponding slice object. Remarks ------- (1) The step (A) would in fact do most of the step (B). For instance, after the step ((Z) and) (A), "a[*x,]" would be a valid expression equivalent to the already valid expression a[(*x,)] satisfying (B). The only thing (B) would add to (A) in concrete terms is it would make a[] a valid expression equivalent to "a[()]" (where "a" may of course be replaced by any Python "primary"). (2) The proposal disagrees with PEP 646 in that, after our steps, the expression of the form "a[*x]" will not get valid. In particular, unlike with PEP 646, we won't have e.g., a[*[y]] as a valid expression which is _not_ equivalent to a[y] The details of PEP 646 on the subject can be found at https://www.python.org/dev/peps/pep-0646/#star-expressions-in-indexes (In either way, "a[*[y],]" would be valid and equivalent to "a[y,]".) Thats' it. I hope to hear your thoughts. Best regards, Takuo Matsuoka
participants (6)
-
2QdxY4RzWzUUiLuE@potatochowder.com
-
Chris Angelico
-
Guido van Rossum
-
Matsuoka Takuo
-
Mxzixl
-
Stephen J. Turnbull