python"或"运算符奇怪的行为

mcl*_*fee 6 python boolean operators

一,代码:

>>> False or 'hello'
'hello'
Run Code Online (Sandbox Code Playgroud)

这种令人惊讶的行为让您检查是否x!= None并在一行中检查x值:

>>> x = 10 if randint(0,2)==1 else None
>>> (x or 0) > 0
depend on x value...
Run Code Online (Sandbox Code Playgroud)

说明:"或"这样的函数:( 链接)"如果x为假,则为y,否则为x"

我所知道的语言不允许你这样做.那么,为什么是Python呢?

aba*_*ert 14

听起来你将两个问题合二为一.

首先,存在短路问题.Marcin的答案完美地解决了这个问题,所以我不会尝试做得更好.

其次,有orand返回的最后一个评估值,而不是将其转换为bool.有两种方式可以争论,你可以在鸿沟的两边找到许多语言.

回到过去的评估值允许的functionCall(x) or defaultValue快捷方式,避免了可能浪费的转换(为什么转换的int 2bool 1,如果你打算用它做的是检查它是否是非零?唯一),通常更容易解释.因此,对于这些原因的各种组合,像C,Lisp,Javascript,Lua,Perl,Ruby和VB这样的语言都是这样做的,Python也是如此.

总是从运算符返回一个布尔值有助于捕获一些错误(特别是在逻辑运算符和按位运算符容易混淆的语言中),并且它允许您设计一种语言,其中布尔检查是严格类型的检查,true而不是只检查非零,它使操作符的类型更容易写出,并且它避免了在两个操作数是不同类型的情况下必须处理转换(请参阅?:C系列语言中的运算符).因此,对于这些原因的各种组合,像C++,Fortran,Smalltalk和Haskell这样的语言都是这样做的.


在您的问题中(如果我理解正确),您正在使用此功能来编写如下内容:

if (x or 0) < 1:
Run Code Online (Sandbox Code Playgroud)

什么时候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
Run Code Online (Sandbox Code Playgroud)

第二个将浪费大量导弹在南极洲两次而不是一次炸毁你的敌人.


如果你很好奇为什么Python这样做:

早在1.x的日子里,没有bool类型.你有falsy值一样None,0,[],(),"",等,以及其他一切是真实的,那么谁需要明确的FalseTrue?返回1or本来傻了,因为1没有更多的不是真正的[1, 2, 3]"dsfsdf".到目前为止bool(逐渐超过两个2.x版本,IIRC),当前的逻辑已经牢固地嵌入到语言中,并且改变会破坏很多代码.

那么,他们为什么不在3.0中改变呢?许多Python用户,包括BDFL Guido,都会建议你不要or在这种情况下使用(至少因为它违反了"TOOWTDI"); 您应该将表达式的结果存储在变量中,例如:

missiles = launchMissiles()
return missiles if missiles else -1
Run Code Online (Sandbox Code Playgroud)

事实上,Guido已经声明他要禁止launchMissiles() or -1,这也是他最终接受三元表达的部分原因if- else他之前曾多次拒绝过这种表达.但是很多人不同意,而Guido是一个 仁慈的 DFL.另外,or按照你期望的方式开展工作,同时拒绝做你想做的事情(但是Guido不想让你想要的话),实际上会非常复杂.


因此,Python可能总是与C,Perl和Lisp在同一侧,而不是与Java,Smalltalk和Haskell相同的一面.


Mar*_*cin 10

我所知道的语言不允许你这样做.那么,为什么Python呢?

那你不懂很多语言.我想不出一种我知道不会表现出这种"短路"行为的语言.

这样做是因为它有用说:

a = b or K
Run Code Online (Sandbox Code Playgroud)

如果b不是None(或其他假的),则a或者变为b,如果不是,则它变为默认值K.

  • "我想不出一种我不知道的语言." (3认同)
  • "我想不出一种我知道的语言不是"c ++,c#java,PHP等,它们都返回布尔值!再想想. (2认同)
  • @Marcin:我相信他谈论的是未能转换为 bool,而不是短路。 (2认同)

hex*_*rot 6

实际上有很多语言.请参阅Wikipedia有关短路评估的信息

至于原因为何短路评价存在,维基百科写道:

如果用作条件的两个表达式都是简单的布尔变量,则实际上可以更快地同时评估布尔运算中使用的两个条件,因为它总是需要一个计算周期,而不是短路评估中使用的一个或两个周期(取决于第一个的价值).

  • 您的报价并未提供*存在短路评估的原因*. (5认同)
  • 我认为问题更多的是关于返回第一个非类似虚假的对象,而不是布尔值.C做到了这一点; C++和Java没有. (2认同)