如何“与"和“或"使用非布尔值? [英] How do "and" and "or" act with non-boolean values?
问题描述
我正在尝试学习python,并遇到了一些不错的代码,虽然简短但并不完全有意义
I'm trying to learn python and came across some code that is nice and short but doesn't totally make sense
上下文是:
def fn(*args):
return len(args) and max(args)-min(args)
我知道它在做什么,但是python为什么要这样做-即返回值而不是True/False?
I get what it's doing, but why does python do this - ie return the value rather than True/False?
10 and 7-2
返回5.同样,将and更改为or将导致功能更改.所以
returns 5. Similarly, changing the and to or will result in a change in functionality. So
10 or 7 - 2
将返回10.
这是合法/可靠的样式,还是对此有任何误解?
Is this legit/reliable style, or are there any gotchas on this?
推荐答案
TL; DR
我们首先总结两个逻辑运算符and
和or
的两种行为.这些习语将构成我们下面讨论的基础.
TL;DR
We start by summarising the two behaviour of the two logical operators and
and or
. These idioms will form the basis of our discussion below.
and
返回第一个Falsy值(如果有),否则返回最后一个 表达式中的值.
and
Return the first Falsy value if there are any, else return the last value in the expression.
or
返回第一个Truthy值(如果有),否则返回最后一个 表达式中的值.
or
Return the first Truthy value if there are any, else return the last value in the expression.
文档中也总结了这种行为,尤其是在此表中:
not
运算符是唯一返回布尔值(无论其操作数如何)的运算符.
The only operator returning a boolean value regardless of its operands is the not
operator.
声明
len(args) and max(args) - min(args)
是"非常 pythonic 的简洁(而且可能可读性较低)的说法,即如果args
不为空,则返回max(args) - min(args)
的结果",否则返回0
.通常,它是if-else
表达式的更简洁表示.例如,
Is a very pythonic concise (and arguably less readable) way of saying "if args
is not empty, return the result of max(args) - min(args)
", otherwise return 0
. In general, it is a more concise representation of an if-else
expression. For example,
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
和用户定义的对象.短路规则也同样适用.
Where exp1
and exp2
are arbitrary python objects, or expressions that return some object. The key to understanding the uses of the logical and
and or
operators here is understanding that they are not restricted to operating on, or returning boolean values. Any object with a truthiness value can be tested here. This includes int
, str
, list
, dict
, tuple
, set
, NoneType
, and user defined objects. Short circuiting rules still apply as well.
但是什么是真实性?
它指的是在条件表达式中使用对象时如何评估对象. @Patrick Haugh在这篇文章中很好地总结了真实性.
But what is truthiness?
It refers to how objects are evaluated when used in conditional expressions. @Patrick Haugh summarises truthiness nicely in this post.
除以下值外,所有值均被视为真实"值: 虚假":
All values are considered "truthy" except for the following, which are "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
None
False
0
0.0
0j
Decimal(0)
Fraction(0, 1)
[]
- an emptylist
{}
- an emptydict
()
- an emptytuple
''
- an emptystr
b''
- an emptybytes
set()
- an emptyset
- an empty
range
, likerange(0)
- objects for which
obj.__bool__()
returnsFalse
obj.__len__()
returns0
真实"值将满足由
if
或while
执行的检查 陈述.我们使用真实"和虚假"来区别于bool
值True
和False
.A "truthy" value will satisfy the check performed by
if
orwhile
statements. We use "truthy" and "falsy" to differentiate from thebool
valuesTrue
andFalse
.
and
的工作方式我们以OP的问题为切入点,讨论了在这些情况下如何使用这些运算符.
How
and
WorksWe build on OP's question as a segue into a discussion on how these operators in these instances.
给出具有定义的函数
Given a function with the definition
def foo(*args): ...
如何返回最小值和最大值之间的差 零个或多个参数的列表中?
How do I return the difference between the minimum and maximum value in a list of zero or more arguments?
找到最大值和最小值很容易(使用内置函数!).这里唯一的障碍是适当地处理参数列表可能为空的特殊情况(例如,调用
foo()
).借助and
运算符,我们可以在一行中完成这两项操作:Finding the minimum and maximum is easy (use the inbuilt functions!). The only snag here is appropriately handling the corner case where the argument list could be empty (for example, calling
foo()
). We can do both in a single line thanks to theand
operator:def foo(*args): return len(args) and max(args) - min(args)
foo(1, 2, 3, 4, 5) # 4 foo() # 0
由于使用了
and
,因此如果第一个为True
,则还必须对第二个表达式求值.请注意,如果第一个表达式的值为真,则返回值为始终第二个表达式的结果.如果第一个表达式的计算结果为Falsy,则返回的结果为第一个表达式的结果.Since
and
is used, the second expression must also be evaluated if the first isTrue
. Note that, if the first expression is evaluated to be truthy, the return value is always the result of the second expression. If the first expression is evaluated to be Falsy, then the result returned is the result of the first expression.在上面的函数中,如果
foo
接收一个或多个参数,则len(args)
大于0
(正数),因此返回的结果为max(args) - min(args)
. OTOH,如果未传递任何参数,则len(args)
是0
,它是Falsy,然后返回0
.In the function above, If
foo
receives one or more arguments,len(args)
is greater than0
(a positive number), so the result returned ismax(args) - min(args)
. OTOH, if no arguments are passed,len(args)
is0
which is Falsy, and0
is returned.请注意,编写此函数的另一种方法是:
Note that an alternative way to write this function would be:
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)
如果有的话,这些函数都不执行任何类型检查,因此,除非您完全信任所提供的输入,否则不要依赖于这些结构的简单性.
If course, none of these functions perform any type checking, so unless you completely trust the input provided, do not rely on the simplicity of these constructs.
我通过一个人为的示例以类似的方式解释了
or
的工作.I explain the working of
or
in a similar fashion with a contrived example.给出具有定义的函数
Given a function with the definition
def foo(*args): ...
您如何完成
foo
以返回9000
上的所有数字?How would you complete
foo
to return all numbers over9000
?我们在这里使用
or
处理拐角处的情况.我们将foo
定义为:We use
or
to handle the corner case here. We definefoo
as: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,因此将其返回(此处发生短路).如果不存在这样的数字,则列表comp的结果为[]
,为Falsy.因此,现在对第二个表达式求值(一个非空字符串)并返回.foo
performs a filtration on the list to retain all numbers over9000
. If there exist any such numbers, the result of the list comprehension is a non-empty list which is Truthy, so it is returned (short circuiting in action here). If there exist no such numbers, then the result of the list comp is[]
which is Falsy. So the second expression is now evaluated (a non-empty string) and is returned.使用条件,我们可以将该函数重新编写为
Using conditionals, we could re-write this function as,
def foo(*args): r = [x for x in args if x > 9000] if not r: return 'No number over 9000!' return r
和以前一样,此结构在错误处理方面更加灵活.
As before, this structure is more flexible in terms of error handling.
这篇关于如何“与"和“或"使用非布尔值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-