TL; DR
我们首先总结两个逻辑运算符and
和的两个行为or
。这些习语将构成我们下面讨论的基础。
and
如果有,则返回第一个Falsy值,否则返回表达式中的最后一个值。
or
如果有,则返回第一个Truthy值,否则返回表达式中的最后一个值。
行为也总结在docs中,尤其是在此表中:
无论其操作数如何,返回布尔值的唯一运算符是该not
运算符。
“真实性”和“真实”评估
该声明
len(args) and max(args) - min(args)
是一种非常 Python式的简洁(并且可能可读性较低)的说法,即“如果args
不为空,则返回结果max(args) - min(args)
”,否则返回0
。通常,它是if-else
表达式的更简洁表示。例如,
exp1 and exp2
应该(大致)翻译为:
r1 = exp1
if r1:
r1 = exp2
或者,等效地,
r1 = exp1 if exp1 else exp2
同样,
exp1 or exp2
相当于
r1 = exp1
if not r1:
r1 = exp2
其中exp1
和exp2
是任意的python对象,或返回某些对象的表达式。在这里理解逻辑and
和or
运算符用法的关键是要理解它们不限于对布尔值进行操作或返回布尔值。任何具有真实性值的对象都可以在此处进行测试。这包括int
,str
,list
,dict
,tuple
,set
,NoneType
,和用户定义的对象。短路规则也同样适用。
但是什么是真实性?
它指的是在条件表达式中使用对象时如何求值。@Patrick Haugh在这篇文章中很好地总结了真实性。
除以下值“ falsy”外,所有值均被视为“真实”值:
None
False
0
0.0
0j
Decimal(0)
Fraction(0, 1)
[]
-一个空的 list
{}
-一个空的 dict
()
-一个空的 tuple
''
-一个空的 str
b''
-一个空的 bytes
set()
-一个空的 set
- 一个空的
range
,像range(0)
- 为其对象
obj.__bool__()
退货 False
obj.__len__()
退货 0
“真实的”值将满足if
或while
语句执行的检查。我们使用“真实的”和“虚假的”来区别
bool
值True
和False
。
如何and
运作
我们以OP的问题为切入点,讨论在这些情况下如何操作这些运算符。
给定一个带有定义的函数
def foo(*args):
...
如何返回零个或多个参数列表中的最小值和最大值之间的差?
找到最小值和最大值很容易(使用内置函数!)。这里唯一的障碍是适当地处理参数列表可能为空的极端情况(例如,调用foo()
)。多亏and
操作员,我们可以在一行中完成这两项操作:
def foo(*args):
return len(args) and max(args) - min(args)
foo(1, 2, 3, 4, 5)
# 4
foo()
# 0
由于and
使用,如果第二个表达式为,则也必须对其求值True
。请注意,如果第一个表达式的值为真,则返回值始终是第二个表达式的结果。如果第一个表达式的计算结果为Falsy,则返回的结果为第一个表达式的结果。
在上面的函数中,如果foo
接收到一个或多个参数,len(args)
则大于0
(一个正数),因此返回的结果为max(args) - min(args)
。OTOH,如果没有参数传递,len(args)
是0
这是Falsy,并0
返回。
请注意,编写此函数的另一种方法是:
def foo(*args):
if not len(args):
return 0
return max(args) - min(args)
或者,更简而言之,
def foo(*args):
return 0 if not args else max(args) - min(args)
当然,如果这些功能都不执行任何类型检查,那么除非您完全信任所提供的输入,否则不要依赖这些结构的简单性。
如何or
运作
我or
用一个人为的例子以类似的方式解释了它的工作。
给定一个带有定义的函数
def foo(*args):
...
您将如何完成foo
所有数字的归还9000
?
我们or
这里用来处理拐角处的情况。我们定义foo
为:
def foo(*args):
return [x for x in args if x > 9000] or 'No number over 9000!'
foo(9004, 1, 2, 500)
# [9004]
foo(1, 2, 3, 4)
# 'No number over 9000!'
foo
对列表执行过滤,以保留上的所有数字9000
。如果存在任何这样的数字,则列表理解的结果是一个非空列表,该列表为Truthy,因此将其返回(此处发生短路)。如果不存在这样的数字,则list comp的结果[]
为Falsy。因此,现在对第二个表达式求值(一个非空字符串)并返回。
使用条件,我们可以将该函数重写为:
def foo(*args):
r = [x for x in args if x > 9000]
if not r:
return 'No number over 9000!'
return r
和以前一样,此结构在错误处理方面更加灵活。
and
(以及or
)不限于使用布尔值或返回布尔值。