python“或”运算符奇怪的行为
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13870378/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
python "or" operator weird behavior
提问by mclafee
First, the code:
首先,代码:
>>> False or 'hello'
'hello'
This surprising behavior lets you check if x != None and check x value in one line:
这种令人惊讶的行为让您可以检查 x != None 并在一行中检查 x 值:
>>> x = 10 if randint(0,2)==1 else None
>>> (x or 0) > 0
depend on x value...
Explanation: "or" functions like this: (link) "if x is false, then y, else x"
解释:“或”函数如下:(链接)“如果 x 为假,则为 y,否则为 x”
No language that i know lets you do this. So, why does Python?
我所知道的任何语言都无法让您这样做。那么,为什么是 Python?
回答by hexparrot
Actually a number of languages do. See Wikipedia about Short-Circuit Evaluation
实际上,许多语言都可以。参见维基百科关于短路评估
For the reason whyshort-circuit evaluation exists, wikipedia writes:
至于原因为何短路评价存在,维基百科写道:
If both expressions used as conditions are simple boolean variables, it can be actually faster to evaluate both conditions used in boolean operation at once, as it always requires a single calculation cycle, as opposed to one or two cycles used in short-circuit evaluation (depending on the value of the first).
如果用作条件的两个表达式都是简单的布尔变量,那么同时计算布尔运算中使用的两个条件实际上会更快,因为它总是需要一个计算周期,而不是短路计算中使用的一两个周期(取决于第一个的值)。
回答by Marcin
No language that i know lets you do this. So, why Python do?
我所知道的任何语言都无法让您这样做。那么,为什么Python呢?
Then you don't know many languages. I can't think of one language that I do know that does not exhibit this "shortcircuiting" behaviour.
那你不懂很多语言。我想不出一种我知道的语言不会表现出这种“短路”行为。
It does it because it is useful to say:
这样做是因为这样说很有用:
a = b or K
such that a either becomes b, if b is not None (or otherwise falsy), and if not it gets the default value K.
使得 a 要么变成 b,如果 b 不是 None (或否则为假),如果不是,则它获得默认值 K。
回答by Ned Batchelder
"No language that i know lets you do this. So, why Python do?" You seem to assume that all languages should be the same. Wouldn't you expect innovation in programming languages to produce unique features that people value?
“我所知道的任何语言都不能让你这样做。那么,为什么 Python 这样做呢?” 您似乎认为所有语言都应该相同。难道您不希望编程语言的创新能够产生人们重视的独特功能吗?
You've just pointed out why it's useful, so why wouldn't Python do it? Perhaps you should ask why other languages don't.
您刚刚指出了它为什么有用,那么为什么 Python 不这样做呢?也许你应该问为什么其他语言没有。
回答by abarnert
It sounds like you're combining two issues into one.
听起来您将两个问题合二为一。
First, there's the issue of short-circuiting. Marcin's answer addresses this issue perfectly, so I won't try to do any better.
首先是短路问题。Marcin 的回答完美地解决了这个问题,所以我不会尝试做得更好。
Second, there's orand andreturning the last-evaluated value, rather than converting it to bool. There are arguments to be made both ways, and you can find many languages on either side of the divide.
其次,有or并and返回最后评估的值,而不是将其转换为 bool。两种方式都有争论,你可以在分歧的两边找到许多语言。
Returning the last-evaluated value allows the functionCall(x) or defaultValueshortcut, avoids a possibly wasteful conversion (why convert an int2into a bool1if the only thing you're going to do with it is check whether it's non-zero?), and is generally easier to explain. So, for various combinations of these reasons, languages like C, Lisp, Javascript, Lua, Perl, Ruby, and VB all do things this way, and so does Python.
返回最后评估的值允许使用functionCall(x) or defaultValue快捷方式,避免可能浪费的转换(如果您要做的唯一事情是检查它是否为非零,为什么将 an 转换int2为 a bool1?),并且通常更容易解释。因此,由于这些原因的各种组合,像 C、Lisp、Javascript、Lua、Perl、Ruby 和 VB 这样的语言都以这种方式做事,Python 也是如此。
Always returning a boolean value from an operator helps to catch some errors (especially in languages where the logical operators and the bitwise operators are easy to confuse), and it allows you to design a language where boolean checks are strictly-typed checks for trueinstead of just checks for nonzero, it makes the type of the operator easier to write out, and it avoids having to deal with conversion for cases where the two operands are different types (see the ?:operator in C-family languages). So, for various combinations of these reasons, languages like C++, Fortran, Smalltalk, and Haskell all do things this way.
始终从运算符返回布尔值有助于捕获一些错误(尤其是在逻辑运算符和位运算符容易混淆的语言中),并且它允许您设计一种语言,其中布尔检查是严格类型检查true而不是只检查非零,它使运算符的类型更容易写出,并且避免在两个操作数是不同类型的情况下处理转换(请参阅?:C 系列语言中的运算符)。因此,由于这些原因的各种组合,C++、Fortran、Smalltalk 和 Haskell 之类的语言都以这种方式工作。
In your question (if I understand it correctly), you're using this feature to be able to write something like:
在您的问题中(如果我理解正确的话),您正在使用此功能来编写如下内容:
if (x or 0) < 1:
When xcould easily be None. This particular use case isn't very useful, both because the more-explicit x if x else 0(in Python 2.5 and later) is just as easy to write and probably easier to understand (at least Guido thinks so), but also because None < 1is the same as 0 < 1anyway (at least in Python 2.x, so you've always got at least one of the two options)… But there are similar examples where it isuseful. Compare these two:
什么时候x可以轻松None。这个特定的用例不是很有用,因为更明确的x if x else 0(在 Python 2.5 及更高版本中)同样容易编写并且可能更容易理解(至少 Guido 是这么认为的),而且因为None < 1与0 < 1任何情况相同(至少在Python 2.x中,所以你总是有两个选项中的至少一个)......但也有类似的例子在那里它是有用的。比较这两个:
return launchMissiles() or -1
return launchMissiles() if launchMissiles() else -1
The second one will waste a lot of missiles blowing up your enemies in Antarctica twice instead of once.
第二个会浪费大量导弹,两次而不是一次炸毁你在南极洲的敌人。
If you're curious why Python does it this way:
如果你好奇 Python 为什么这样做:
Back in the 1.x days, there wasno booltype. You've got falsy values like None, 0, [], (), "", etc., and everything else is true, so who needs explicit Falseand True? Returning 1from orwould have been silly, because 1is no more true than [1, 2, 3]or "dsfsdf". By the time boolwas added (gradually over two 2.x versions, IIRC), the current logic was already solidly embedded in the language, and changing would have broken a lot of code.
早在1.x的日子里,是没有bool类型。你有像None, 0, [], (),""等的虚假值,而其他一切都是真的,那么谁需要明确的False和True?返回1fromor会很傻,因为1不比[1, 2, 3]or更真实"dsfsdf"。到bool添加的时候(逐渐超过两个 2.x 版本,IIRC),当前的逻辑已经牢固地嵌入到语言中,更改会破坏很多代码。
So, why didn't they change it in 3.0? Many Python users, including BDFL Guido, would suggest that you shouldn't use orin this case (at the very least because it's a violation of "TOOWTDI"); you should instead store the result of the expression in a variable, e.g.:
那么,他们为什么不在 3.0 中更改它呢?许多 Python 用户,包括 BDFL Guido,会建议您不要or在这种情况下使用(至少因为它违反了“TOOWTDI”);您应该将表达式的结果存储在一个变量中,例如:
missiles = launchMissiles()
return missiles if missiles else -1
And in fact, Guido has stated that he'd like to ban launchMissiles() or -1, and that's part of the reason he eventually accepted the ternary if-elseexpression that he'd rejected many times before. But many others disagree, and Guido is a benevolentDFL. Also, making orwork the way you'd expect everywhere else, while refusing to do what you want (but Guido doesn't want you to want) here, would actually be pretty complicated.
而事实上,圭多曾表示,他希望禁止launchMissiles() or -1,这是他最终接受了三元的部分原因if-else表达的是他以前拒绝了很多次。但许多其他人不同意,Guido 是一个 仁慈的DFL。此外,or在其他任何地方都按照您期望的方式工作,同时拒绝在这里做您想做的事情(但 Guido 不希望您这样做),实际上会非常复杂。
So, Python will probably always be on the same side as C, Perl, and Lisp here, instead of the same side as Java, Smalltalk, and Haskell.
因此,Python 在这里可能永远与 C、Perl 和 Lisp 站在同一边,而不是与 Java、Smalltalk 和 Haskell 站在同一边。
回答by MestreLion
This behavior is not surprising, and it's quite straightforward if you consider Python has the following features regarding or, andand notlogical operators:
这种现象并不奇怪,如果你认为Python有以下特点有关这是相当简单的或,并和不逻辑运算符:
- Short-circuit evaluation: it only evaluates operands up to where it needs to.
- Non-coercing result: the result is one of the operands, not coerced to
bool.
- 短路评估:它只评估操作数到它需要的地方。
- 非强制结果:结果是操作数之一,不会被强制为
bool。
And, additionally:
而且,另外:
- The Truth Valueof an object is Falseonly for
None,False,0,"",[],{}. Everything else has a truth value of True(this is a simplification; the correct definition is in the official docs)
- 对象的真值仅对于、、、、、是False。其他所有东西的真值都是True(这是一种简化;正确的定义在官方文档中)
NoneFalse0""[]{}
Combine those features, and it leads to:
结合这些功能,它会导致:
- or: if the firstoperand evaluates as True, short-circuit there and return it. Or return the 2nd operand.
- and: if the firstoperand evaluates as False, short-circuit there and return it. Or return the 2nd operand.
- 或:如果第一个操作数的计算结果为True,则在那里短路并返回它。或者返回第二个操作数。
- and: 如果第一个操作数的计算结果为False,则在那里短路并返回它。或者返回第二个操作数。
It's easier to understand if you generalize to a chain of operations:
如果您概括为一系列操作,则更容易理解:
>>> a or b or c or d
>>> a and b and c and d
Here is the "rule of thumb" I've memorized to help me easily predict the result:
这是我记住的“经验法则”,可帮助我轻松预测结果:
- or: returns the first "truthy"operand it finds, or the last one.
- and: returns the first "falsy"operand it finds, or the last one.
- 或: 返回它找到的第一个“真实”操作数,或最后一个。
- and: 返回它找到的第一个“假”操作数,或最后一个。
As for your question, on whypython behaves like that, well... I think because it has some very neat uses, and it's quite intuitive to understand. A common use is a series of fallback choices, the first "found" (ie, non-falsy) is used. Think about this silly example:
至于你的问题,为什么python会这样,嗯......我认为是因为它有一些非常巧妙的用途,而且理解起来非常直观。一个常见的用途是一系列回退选择,使用第一个“发现”(即非假)。想想这个愚蠢的例子:
drink = getColdBeer() or pickNiceWine() or random.anySoda or "meh, water :/"
Or this real-world scenario:
或者这个真实世界的场景:
username = cmdlineargs.username or configFile['username'] or DEFAULT_USERNAME
Which is much more concise andelegant than the alternative.
这比替代方案更加简洁和优雅。
As many other answers have pointed out, Python is not alone and many other languages have the same behavior, for both short-circuit (I believe mostcurrent languanges are) and non-coercion.
正如许多其他答案所指出的那样,Python 并不孤单,许多其他语言都有相同的行为,无论是短路(我相信大多数当前的语言都是)还是非强制。

