by 2arrs2ells on 5/2/20, 2:23 AM with 217 comments
by stinos on 5/2/20, 6:24 AM
Apart from unexpected behavior it is also about readability: with parentheses in place you can just read left-to-right and the parsing overhead is minimal. Without them though, you have to read almost everything first, parse what is there, figure out what comes first (and hope you remembred it correctly), then read again to get a mental image of what is actually going on.
by BurningFrog on 5/2/20, 3:19 AM
But I can't think of any case with `==` type operators, or really any other operators where it also makes sense.
So was that maybe an overgeneralized feature that should have been limited to the math operators?
by Figs on 5/2/20, 3:51 AM
by userbinator on 5/2/20, 4:40 AM
by fhars on 5/2/20, 9:03 AM
by m12k on 5/2/20, 8:55 AM
by nickcw on 5/2/20, 10:26 AM
That isn't surprising I suppose however what is surprising is that I wrote gpython and I had no idea why it worked until I read the explanation on stack overflow about 5 times.
I guess that is the power of having implementing the grammar.
I always like it when my creations (programs or children) exceed me :-)
by jgoodknight on 5/2/20, 5:36 AM
by bnegreve on 5/2/20, 4:53 AM
>>> def check_parity(x, expect_odd):
... odds = [ 1, 3, 5 ]
... if x in odds == expect_odd :
... print("ok")
... else:
... print("error")
...
>>> check_parity(5, True)
error
Crazy!by koliber on 5/2/20, 11:40 AM
Part of the issue is that “==“ and “is” are intermixed. That emphasizes the weirdness but detracts from understanding the underlying mechanism that is at work.
If you look at
True == False == False
It makes more a bit sense that it evaluates the way it does.
If you do
1 == 2 == 2
and it evaluates to False, then it is perfectly clear.
by lifthrasiir on 5/2/20, 11:44 AM
It is pretty common that arithmetic comparison operators are grouped to a single precedence level and that's not a problem. But in Python `is`, `is not`, `in` and `not in` are also in that level. In particular two operands of `in` and `not in` have different [1] types unlike others. Mixing them are, either with or without chained operators, almost surely incorrect.
This kind of precedence issue can be solved by introducing non-associative pairs of operators (or precedence levels), something that---unfortunately---I don't see much in common programming languages. Ideally Python's operator precedence table should look like this (compare with the current documentation [2]):
Operator Description
-------------------------------------- ------------------------
... ...
`not x` Boolean NOT
_______________________________________________________________
|
| The following groups do not mix to each other.
| Use parentheses to clarify what you mean.
| ______________________________________________________________
||
|| `in`, `not in` Membership tests
||
|| `is`, `is not` Identity tests
||
|| `<`, `<=`, `>`, `>=`, `!=`, `==` Comparisons
||______________________________________________________________
|_______________________________________________________________
`|` Bitwise OR
... ...
In fact, there is already one non-associative pair in Python: `not` and virtually every operator except boolean operators. It is understandable: the inability to parse `3 + not 4` is marginal but you don't want `3 is not 4` to be parsed as `3 is (not 4)`. My point is that, if we already have such a pair why can't we have more?[1] With an exception of strings (`"a" in "abcdef"`). I hate that Python doesn't have a character type.
[2] https://docs.python.org/3.8/reference/expressions.html#opera...
by 6gvONxR4sf7o on 5/2/20, 6:18 AM
by bannatech on 5/2/20, 3:36 AM
by jasonpeacock on 5/2/20, 2:56 PM
It doesn't matter what the result is - you know it's going to bite you eventually. If you run a linter on this it would correctly yell at you.
by thisisyuu on 5/2/20, 3:48 PM
by breatheoften on 5/2/20, 3:00 AM
by forumranger on 5/5/20, 7:46 PM
>>> True is (False is False)
True
>>> True == (False is False)
True
by njharman on 5/2/20, 10:25 AM
>>> (True == False) is False
True
by raylu on 5/2/20, 5:58 AM
Yeah, that was a real head-scratcher.
by choward on 5/2/20, 3:41 PM
by kingname on 5/6/20, 3:49 AM
by echelon on 5/2/20, 9:15 AM
True = False
This is right up there with default arg instances getting cached across calls, though it's perhaps better suited for an underhanded Python competition.
Have fun with it. Redefine it to be true 90% of the time.
by Animats on 5/2/20, 3:45 AM
Python 3.6.9 (default, Apr 18 2020, 01:56:04)
>>> True == False is False
False
>>> (True == False) is False
True
There are worse problems with Python's "is". >>> 1+1 is 2
True
>>> 1000+1000 is 2000
False
This comes from a bad idea borrowed from LISP. Numbers are boxed, and the small integers have boxes built in for them. Larger numbers have boxes dynamically generated. In Python "is" means "in the same box". This corresponds to (eq a b) in LISP.[1] Exposing the implementation like that might have been a good idea when McCarthy came up with it in 1960.[1] http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node74.html