This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: ++ does not throw a SyntaxError
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.9
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Marco Sulla, eric.snow, steven.daprano
Priority: normal Keywords:

Created on 2020-02-01 10:48 by Marco Sulla, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (7)
msg361159 - (view) Author: Marco Sulla (Marco Sulla) * Date: 2020-02-01 10:48
Python 3.9.0a0 (heads/master-dirty:d8ca2354ed, Oct 30 2019, 20:25:01) 
[GCC 9.2.1 20190909] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 ++ 2
3

This is probably because the interpreter reads:

1 + +2

1. ++ could be an operator in future. Probably not. Probably never. But you never know.
2. A space between an unary operator and the object should not be allowed
3. the first expression is clearly unreadable and hard to understand, so completely unpythonic
msg361165 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2020-02-01 12:21
This is not a bug, as you have pointed out yourself you are using a binary plus and a unary plus operator in the same expression.

This has been part of Python since version 1, and with operator overloading `obj + +thing` could mean whatever the objects want the two operators to mean. Unary plus is not necessarily a no-op. For example, the Decimal class gives a meaning to unary plus.

`++` should never be an operator in the future, precisely because it already has a meaning today (either two unary pluses, or binary plus followed by unary plus). Even if the compiler could distinguish between the cases, the human reader would not.

The first expression is not "unreadable". The fact that you were able to read it and diagnose it yourself as a binary operator followed by a unary operator proves that you can, in fact, read it. And it probably wasn't that hard to understand. (It wasn't for me.)

It would be easier to read if you used spaces around the binary plus and no space between the unary plus and its operand, but it can still be read and understood even with the unusual spacing.
msg361168 - (view) Author: Marco Sulla (Marco Sulla) * Date: 2020-02-01 14:56
> This is not a bug
No one said it's a bug. It's a defect.

> This has been part of Python since version 1
There are many things that was part of Python 1 that was removed.

> `++` should never be an operator in the future, precisely because it already has a meaning today

This is not a "meaning". `++` means nothing. Indeed

>>> 1++
  File "<stdin>", line 1
    1++
      ^
SyntaxError: invalid syntax

> The first expression is not "unreadable". The fact that you were able to read it and diagnose it [...]

The fact I understood it it's because I'm a programmer with more than 10 years of experience, mainly in Python. And I discovered this defect by acccident, because I wanted to write `a += b` and instead I wrote `a ++ b`. And when happened, I didn't realized why it didn't raised a SyntaxError or, at least, a SyntaxWarning. I had to take some minutes to realize the problem. 

So, in my "humble" opinion, it's *highly* unreadable and surprising.
msg361171 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2020-02-01 15:34
Marco, this is no more of a defect than `x*-y` or `a&~b`. It is a binary 
operator followed by an unary operator, just like `x--y`, `x/-y`, 
`x+-y`, `x**-y` etc. Python has at least three unary operators and at 
least 17 binary operators so in total there are 51 possible legal 
combinations of a binary operator followed by an unary operator.

`++` isn't special, it's not unique, or a defect, or a bug.

>     1++
>       ^
> SyntaxError: invalid syntax

As a programmer with more than 10 years experience, you should know that 
this example is a syntax error because you are missing the right hand 
operand, not because `++` has no meaning. You would get precisely the 
same syntax error with `2*` or `2==`.
msg361186 - (view) Author: Marco Sulla (Marco Sulla) * Date: 2020-02-01 19:15
> `++` isn't special

Indeed the problem is that no error or warning is raised if two operators are consecutive, without a space between. All the cases you listed are terribly unreadable and hardly intelligible. 

Anyway I do not agree `++` is not special:

> you should know that this example is a syntax error because you are missing the right hand operand, not because `++` has no meaning

But you should know that in a *lot* of other popular languages, `++` and `--` are unary operators, so it's particularly surprisingly to see that they *seems* to work in Python, even if they *seems* to be a binary operator.

This is completely confusing and messy. Frankly, I'm not a PEP 8 orthodox at all. I think that you can write `a+b`. It's not elegant, it's a bit less readable that `a + b`, but it's not the end of the world. 

But you should *not* be allowed to write `a+-b` without at least a warning, because `+-` seems a binary operator. And you should not be able to write `a+ -b` too, with the interpreter that acts like Ponzio Pilato, because what's this? Is it an unary `+` or an unary `-`? 
We know the unary is the `-`, `a+` has no sense. but for someone that does not know Python, __it's not readable__. So, IMHO, the interpreter should at least raise a warning if the syntax is not: 
`a + -b`
for any combination of binary and unary operators.
msg361350 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2020-02-04 15:04
FWIW, this is the sort of thing that is usually best suited to be reported by linters, not the Python runtime.
msg361364 - (view) Author: Marco Sulla (Marco Sulla) * Date: 2020-02-04 19:49
> this is the sort of thing that is usually best suited to be reported by linters, not the Python runtime.

TL;DR: if you write something like `a -- b`, it's quite extraordinary that you really wanted to write this. You probably wanted to write `a - -b` or, more probably, `a -= b`. So the parser is **masking a potential subtle bug**, that can cause hours of stressing debugging, because probably the program will run without problem but gives you a wrong result, or will throw an exception but in a completely different point.

Long version:

Normally I agree, but not in this case.

PEP 8 defines line guides for writing a more readable code. They are not mandatory because:

1. there are cases in which is more readable if you not follow PEP 8 (for example, using `\` with long `with` statements)
2. there are cases in which the rule is not followed because of using it in fast tests (as for from module import *)
3. sometimes is simply not possible to follow PEP 8 (for example, many classes can easily implement __eq__, but implementing all the other comparison operators many times is simply not possible)
4. sometimes the recommendation can't be followed, because it's not what you want to achive (for example, sometimes you need to check the exact class of an object and use `type(a) == SomeClass` instead of `isinstance(a, SomeClass)`)
5. there are cases that PEP 8 does not work. For example, bool(numpy.ndarray) does not work, you must do len(numpy.ndarray)
6. sometimes, it's simply a matter of style. One prefers a style, another one prefer another style

That said, none of these valid border cases can be applied to this case:

1. `a+-b` can be NEVER more readable than `a + -b`
2. `a++b` is clearly faster because you have to write... 2 spaces less. Well, I think that you'll never write a ton of binary operators followed by a unary one, so I suppose two little blank spaces does not slow down you too much :-D
3. it's always possible to separate `a * -b`, for example
4. if you write something like `a -- b`, it's quite extraordinary that you really wanted to write this. You probably wanted to write `a - -b` or, more probably, `a -= b`. So the parser is **masking a potential subtle bug**, that can cause hours of stressing debugging, because probably the program will run without problem but gives you a wrong result, or will throw an exception but in a completely different point.
5. See 3
6. this is IMHO not a matter of style. Writing `a ++ b` is simply ugly, **much** unreadable and prone to errors.
History
Date User Action Args
2022-04-11 14:59:26adminsetgithub: 83697
2020-02-04 19:49:31Marco Sullasetmessages: + msg361364
2020-02-04 15:04:37eric.snowsetnosy: + eric.snow
messages: + msg361350
2020-02-01 19:15:34Marco Sullasetmessages: + msg361186
2020-02-01 15:34:13steven.dapranosetmessages: + msg361171
2020-02-01 14:56:43Marco Sullasetmessages: + msg361168
2020-02-01 12:21:39steven.dapranosetstatus: open -> closed

nosy: + steven.daprano
messages: + msg361165

resolution: not a bug
stage: resolved
2020-02-01 10:48:00Marco Sullacreate