首先,代码:
>>> False or 'hello'
'hello'
这种令人惊讶的行为让你检查是否x!= None并在一行中检查x值:
>>> x = 10 if randint(0,2)==1 else None
>>> (x or 0) > 0
depend on x value...
说明:“或”这样的函数:(link) “如果x为假,则为y,否则为x”
我所知道的语言不允许你这样做。 那么,为什么是Python呢?
答案 0 :(得分:13)
听起来你将两个问题合二为一。
首先,存在短路问题。 Marcin的答案完美地解决了这个问题,所以我不会尝试做得更好。
其次,or
和and
返回最后评估的值,而不是将其转换为bool。有两种方式可以争论,你可以在鸿沟的两边找到许多语言。
返回最后评估的值可以使用functionCall(x) or defaultValue
快捷方式,避免可能造成浪费的转化(如果将int
2
转换为bool
1
,你要做的唯一事情是检查它是否为非零?),通常更容易解释。因此,对于这些原因的各种组合,像C,Lisp,Javascript,Lua,Perl,Ruby和VB这样的语言都是这样做的,Python也是如此。
始终从运算符返回布尔值有助于捕获一些错误(特别是在逻辑运算符和按位运算符容易混淆的语言中),并且它允许您设计一种布尔检查是严格类型检查的语言对于true
而不是仅检查非零,它使得运算符的类型更容易写出,并且它避免了在两个操作数是不同类型的情况下必须处理转换(参见?:
C家族语言的运算符)。因此,对于这些原因的各种组合,像C ++,Fortran,Smalltalk和Haskell这样的语言都是这样做的。
在您的问题中(如果我理解正确),您正在使用此功能来编写类似的内容:
if (x or 0) < 1:
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
第二个将浪费大量导弹在南极洲炸毁你的敌人而不是一次。
如果你很好奇为什么Python会这样做:
回到1.x天, 没有bool
类型。您有None
,0
,[]
,()
,""
等虚假值,其他一切都是真的,所以谁需要明确False
和True
?从1
返回or
本来就很愚蠢,因为1
不比[1, 2, 3]
或"dsfsdf"
更真实。当bool
被添加时(逐渐超过两个2.x版本,IIRC),当前的逻辑已经牢固地嵌入到语言中,并且改变会破坏很多代码。
那么,他们为什么不在3.0中改变呢?许多Python用户,包括BDFL Guido,都会建议你不要在这种情况下使用or
(至少因为它违反了“TOOWTDI”);您应该将表达式的结果存储在变量中,例如:
missiles = launchMissiles()
return missiles if missiles else -1
事实上,Guido已经声明他要禁止launchMissiles() or -1
,这也是他最终接受三元if
- else
表达的部分原因。以前多次拒绝过。但是其他许多人不同意,而Guido是一个仁慈的 DFL。另外,让or
按照你期望的方式工作,同时拒绝做你想做的事情(但是Guido不想让你想要的话),实际上会非常复杂。
因此,Python可能总是与C,Perl和Lisp在同一侧,而不是与Java,Smalltalk和Haskell相同的一面。
答案 1 :(得分:10)
我所知道的语言不允许你这样做。那么,为什么Python呢?
然后你不懂很多语言。我想不出一种我所知道的并不表现出这种“短路”行为的语言。
这样做是因为说:
很有用a = b or K
如果b不是None(或其他假的),则a或者变为b,如果不是,则变为默认值K.
答案 2 :(得分:6)
实际上有很多语言都可以。请参阅Wikipedia关于Short-Circuit Evaluation
由于 为什么 存在短路评估的原因,维基百科写道:
如果用作条件的两个表达式都是简单的布尔变量, 实际上可以更快地评估布尔值中使用的两个条件 一次操作,因为它总是需要一个计算周期, 而不是短路评估中使用的一个或两个周期 (取决于第一个的值)。
答案 3 :(得分:2)
这种行为并不令人惊讶,如果您认为Python具有以下关于或,和以及不的的功能,那么这一点非常简单strong>逻辑运算符:
bool
。另外:
None
,False
,{{1} False },0
,""
,[]
。其他一切都有 True 的真值(这是一种简化;正确的定义在official docs )结合这些功能,它会导致:
如果您推广到一系列操作,这会更容易理解:
{}
这是&#34;经验法则&#34;我已经记住了,可以帮助我轻松预测结果:
至于你的问题,在 为什么 python的行为就像那样,嗯...我认为因为它有一些非常巧妙的用途,而且相当不错直观易懂。一个常见的用途是一系列后备选择,第一个&#34;发现&#34; (即,非虚假)被使用。想想这个愚蠢的例子:
>>> a or b or c or d
>>> a and b and c and d
或者这个真实场景:
drink = getColdBeer() or pickNiceWine() or random.anySoda or "meh, water :/"
比其他选择更简洁和更优雅。
正如许多其他答案所指出的那样,Python并不是唯一的,许多其他语言具有相同的行为,因为短路(我相信大多数当前语言都是)和非强制。< / p>
答案 4 :(得分:1)
“我所知道的语言不允许你这样做。那么,为什么Python会这样做?”您似乎假设所有语言都应该相同。难道您不期望编程语言的创新能够产生人们重视的独特功能吗?
你刚才指出它为什么有用,为什么Python不这样做呢?也许你应该问为什么其他语言没有。
答案 5 :(得分:0)
您可以在布尔上下文之外利用 Python 或运算符的特殊功能。经验法则仍然是布尔表达式的结果是第一个 true
操作数或行中的最后一个。
请注意,逻辑运算符(或包含的)在赋值运算符 =
之前进行计算,因此您可以像处理普通表达式一样将布尔表达式的结果赋值给变量:>
>>> a = 1
>>> b = 2
>>> var1 = a or b
>>> var1
1
>>> a = None
>>> b = 2
>>> var2 = a or b
>>> var2
2
>>> a = []
>>> b = {}
>>> var3 = a or b
>>> var3
{}
此处,or
运算符按预期工作,如果计算结果为 true
,则返回第一个 false
操作数或最后一个操作数。