TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Why does `True == False is False` evaluate to False in Python? (2013)

268 点作者 2arrs2ells大约 5 年前

23 条评论

stinos大约 5 年前
One of the comments lays out why I probably never use things like this: <i>And this is exactly why I tend to wrap compound logical comparisons in parens, I simply can&#x27;t remember the syntax across all the languages I use, and it&#x27;s not worth the risk of leaving them off and having unexpected behavior</i><p>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.
评论 #23051202 未加载
评论 #23051063 未加载
评论 #23049829 未加载
评论 #23051489 未加载
评论 #23050002 未加载
BurningFrog大约 5 年前
I like chained comparisons for the `10 &lt; x &lt;= 100`, since it makes intuitive sense and removes duplication.<p>But I can&#x27;t think of any case with `==` type operators, or really <i>any</i> other operators where it also makes sense.<p>So was that maybe an overgeneralized feature that should have been limited to the math operators?
评论 #23049793 未加载
评论 #23048875 未加载
评论 #23048912 未加载
评论 #23048868 未加载
评论 #23048886 未加载
Figs大约 5 年前
If anyone&#x27;s looking for some more good WTFs in Python: <a href="https:&#x2F;&#x2F;github.com&#x2F;satwikkansal&#x2F;wtfpython" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;satwikkansal&#x2F;wtfpython</a>
评论 #23049759 未加载
评论 #23049379 未加载
评论 #23055568 未加载
评论 #23049568 未加载
评论 #23049724 未加载
评论 #23049823 未加载
userbinator大约 5 年前
This seems to be another instance of the general situation where trying to &quot;helpful&quot; by introducing a special-case rule (comparison chaining) that is intended to make some uses more convenient, also introduces perplexing behaviour for other cases. I&#x27;m far more accustomed to the C-family languages, where parsing is usually quite uniform, so to me &quot;these operators are binary and left-associative like all the others, except when more than one occur in an expression&quot; seems like a trap. I wonder if the short-circuiting behaviour of the implicit &amp;&amp; has also caused some surprises, even in the x &lt; y &lt; z() type of expressions that this feature was intended for.
评论 #23049528 未加载
fhars大约 5 年前
I can‘t help but read most of the moaning about Python‘s handling of chained comparisons in this thread as “I already know how Blubb handles comparisons, thank you very much, and if Python doesn’t do it exactly the same way Blubb does, Python is obviously stupid and it’s designers must be morons.”
m12k大约 5 年前
I honestly don&#x27;t think being able to write &#x27;a &lt; b &lt; c&#x27; is worth making the language bigger and causing weirdness and gotchas like this. &#x27;a &lt; b &amp;&amp; b &lt; c&#x27; isn&#x27;t that much longer and is instantly and unambiguously readable to programmers coming from hundreds of other languages.
评论 #23050500 未加载
评论 #23050895 未加载
评论 #23050941 未加载
nickcw大约 5 年前
I tried this in gpython ( <a href="https:&#x2F;&#x2F;github.com&#x2F;go-python&#x2F;gpython" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;go-python&#x2F;gpython</a> ) and it works.<p>That isn&#x27;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.<p>I guess that is the power of having implementing the grammar.<p>I always like it when my creations (programs or children) exceed me :-)
jgoodknight大约 5 年前
I find it cool to explore these edge cases, but putting anything like this in a real code base is a terrible idea BECAUSE there are so many different ways to interpret it. Sure a &lt; b &lt;= c has a clear mathematical meaning which works towards python&#x27;s overall mission of being clear, but in general please good people only have one or two variables in your conditional statements!
bnegreve大约 5 年前
I find something like this totally plausible and yet it is completely wrong.<p><pre><code> &gt;&gt;&gt; def check_parity(x, expect_odd): ... odds = [ 1, 3, 5 ] ... if x in odds == expect_odd : ... print(&quot;ok&quot;) ... else: ... print(&quot;error&quot;) ... &gt;&gt;&gt; check_parity(5, True) error </code></pre> Crazy!
评论 #23049630 未加载
评论 #23049436 未加载
koliber大约 5 年前
This is neat. My first reaction was confusion and a bit of shock. But then it made sense. And it makes a lot of sense.<p>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.<p>If you look at<p>True == False == False<p>It makes more a bit sense that it evaluates the way it does.<p>If you do<p>1 == 2 == 2<p>and it evaluates to False, then it is perfectly clear.
lifthrasiir大约 5 年前
There are many kinds of chained operators (in some languages even associative arithmetic operators are chained). Contrary to popular beliefs, this is nothing to do with chained operators but rather with operator precedences.<p>It is pretty common that arithmetic comparison operators are grouped to a single precedence level and that&#x27;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.<p>This kind of precedence issue can be solved by introducing non-associative pairs of operators (or precedence levels), something that---unfortunately---I don&#x27;t see much in common programming languages. Ideally Python&#x27;s operator precedence table should look like this (compare with the current documentation [2]):<p><pre><code> 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 || || `&lt;`, `&lt;=`, `&gt;`, `&gt;=`, `!=`, `==` Comparisons ||______________________________________________________________ |_______________________________________________________________ `|` Bitwise OR ... ... </code></pre> 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&#x27;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&#x27;t we have more?<p>[1] With an exception of strings (`&quot;a&quot; in &quot;abcdef&quot;`). I hate that Python doesn&#x27;t have a character type.<p>[2] <a href="https:&#x2F;&#x2F;docs.python.org&#x2F;3.8&#x2F;reference&#x2F;expressions.html#operator-precedence" rel="nofollow">https:&#x2F;&#x2F;docs.python.org&#x2F;3.8&#x2F;reference&#x2F;expressions.html#opera...</a>
6gvONxR4sf7o大约 5 年前
It seems like only operators with a nice transitivity should be supported. x &lt; y &lt; z. x == y == z. x is y is z. That kind of thing. x != y != z doesn&#x27;t work because in normal language, you&#x27;d say that to mean that they&#x27;re all unique, while allowing it the python way, it doesn&#x27;t imply x != z.
bannatech大约 5 年前
I wrote up a post on this same kind of expression: <a href="https:&#x2F;&#x2F;banna.tech&#x2F;post&#x2F;chained_conditional_expressions_in_python&#x2F;" rel="nofollow">https:&#x2F;&#x2F;banna.tech&#x2F;post&#x2F;chained_conditional_expressions_in_p...</a>
jasonpeacock大约 5 年前
You&#x27;re mixing comparison operators (`==` and `is`), which is a code smell.<p>It doesn&#x27;t matter what the result is - you know it&#x27;s going to bite you eventually. If you run a linter on this it would correctly yell at you.
评论 #23052746 未加载
thisisyuu大约 5 年前
Someone writing code like these, his life is sad.
评论 #23052714 未加载
breatheoften大约 5 年前
does ruby do anything like this? i&#x27;m new to ruby and could imagine something like this biting me ...
评论 #23048786 未加载
评论 #23048857 未加载
forumranger大约 5 年前
<p><pre><code> &gt;&gt;&gt; True is (False is False) True &gt;&gt;&gt; True == (False is False) True</code></pre>
njharman大约 5 年前
Explicit is better than implicit.<p><pre><code> &gt;&gt;&gt; (True == False) is False True</code></pre>
raylu大约 5 年前
Oh, hi!<p>Yeah, that was a real head-scratcher.
choward大约 5 年前
170 comments here so far because of some syntactic sugar. If it causes this much discussion and confusion it&#x27;s not worth it IMO. I&#x27;m glad none of the languages I use have this &quot;feature&quot;.
kingname大约 5 年前
tl,dr: if you know why does the result of `1 &lt; 2 &lt; 3` is True,then,you know why `True == False is False` is False. Forget other language, first. In Python the chain compare means `1 &lt; 2 &lt; 3` means `1 &lt; 2 and 2 &lt; 3`, so `True == False is False` means `True == False and False is False` and equal to `False and True`. So, the result is False.
echelon大约 5 年前
This can be fixed by one of my favorite Python oddities,<p>True = False<p>This is right up there with default arg instances getting cached across calls, though it&#x27;s perhaps better suited for an underhanded Python competition.<p>Have fun with it. Redefine it to be true 90% of the time.
评论 #23050492 未加载
评论 #23050857 未加载
Animats大约 5 年前
It&#x27;s just a operator precedence problem. Add parentheses and it goes away.<p><pre><code> Python 3.6.9 (default, Apr 18 2020, 01:56:04) &gt;&gt;&gt; True == False is False False &gt;&gt;&gt; (True == False) is False True </code></pre> There are worse problems with Python&#x27;s &quot;is&quot;.<p><pre><code> &gt;&gt;&gt; 1+1 is 2 True &gt;&gt;&gt; 1000+1000 is 2000 False </code></pre> 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 &quot;is&quot; means &quot;in the same box&quot;. 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.<p>[1] <a href="http:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;Groups&#x2F;AI&#x2F;html&#x2F;cltl&#x2F;clm&#x2F;node74.html" rel="nofollow">http:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;Groups&#x2F;AI&#x2F;html&#x2F;cltl&#x2F;clm&#x2F;node74.html</a>
评论 #23049024 未加载
评论 #23049025 未加载
评论 #23052272 未加载
评论 #23049009 未加载
评论 #23049110 未加载
评论 #23049061 未加载
评论 #23049102 未加载
评论 #23049016 未加载
评论 #23049052 未加载
评论 #23050032 未加载