Mar*_*cin 84 python operators logical-operators
我正在尝试学习python,并且遇到了一些既好又短的代码,但并不完全有意义
背景是:
def fn(*args):
return len(args) and max(args)-min(args)
Run Code Online (Sandbox Code Playgroud)
我得到它正在做的事情,但为什么python这样做 - 即返回值而不是True/False?
10 and 7-2
Run Code Online (Sandbox Code Playgroud)
返回5.同样,更改和将导致或将导致功能更改.所以
10 or 7 - 2
Run Code Online (Sandbox Code Playgroud)
会回来10.
这是合法/可靠的风格,还是有任何问题?
cs9*_*s95 116
我们通过总结两个逻辑运算符的两个行为开始and
和or
.这些习语将成为我们下面讨论的基础.
and
如果有,则返回第一个Falsey值,否则返回表达式中的最后一个值.
or
如果有的话,返回第一个Truthy值,否则返回表达式中的最后一个值.
无论操作数如何,唯一返回布尔值的not
运算符是运算符.
该声明
len(args) and max(args) - min(args)
Run Code Online (Sandbox Code Playgroud)
是一种非常 pythonic简洁(可以说是不太可读)的方式说"如果args
不是空的,返回结果max(args) - min(args)
",否则返回0
.通常,它是if-else
表达式的更简洁表示.例如,
exp1 and exp2
Run Code Online (Sandbox Code Playgroud)
应该(粗略地)翻译成:
r1 = exp1
if r1:
r1 = exp2
Run Code Online (Sandbox Code Playgroud)
或者,等效地,
r1 = exp1 if exp1 else exp2
Run Code Online (Sandbox Code Playgroud)
where exp1
和exp2
是任意python对象,或返回某些对象的表达式.理解逻辑and
和or
运算符的使用的关键是理解它们不限于操作或返回布尔值.任何具有真值的对象都可以在这里测试.这包括int
,str
,list
,dict
,tuple
,set
,NoneType
,和用户定义的对象.短路规则仍然适用.
但是什么是真实性?
它指的是在条件表达式中使用对象的方式.@Patrick Haugh在这篇文章中很好地总结了真实性.
所有值都被认为是"真实的",除了以下是"假的":
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
A"truthy"值将符合执行检查
if
或while
语句.我们使用"truthy"和"falsy"来区bool
分值True
和False
.
and
工作我们以OP的问题为基础,讨论这些运算符在这些情况下的运作方式.
给定定义的函数
Run Code Online (Sandbox Code Playgroud)exp1 or exp2
如何在零个或多个参数列表中返回最小值和最大值之间的差异?
找到最小值和最大值很容易(使用内置函数!).这里唯一的障碍是适当地处理参数列表可能为空(例如,调用foo()
)的极端情况.由于and
运营商,我们可以在一条线上做到这两点:
r1 = exp1
if not r1:
r1 = exp2
Run Code Online (Sandbox Code Playgroud)
def foo(*args):
...
Run Code Online (Sandbox Code Playgroud)
自and
使用以来,如果第一个表达式,则还必须评估第二个表达式True
.请注意,如果第一个表达式被评估为真实,则返回值始终是第二个表达式的结果.如果第一个表达式被评估为Falsey,则返回的结果是第一个表达式的结果.
在上面的函数中,如果foo
接收到一个或多个参数,len(args)
则大于0
(正数),因此返回的结果是max(args) - min(args)
.OTOH,如果没有参数传递,len(args)
是0
这是Falsey,并0
返回.
请注意,编写此函数的另一种方法是:
def foo(*args):
return len(args) and max(args) - min(args)
Run Code Online (Sandbox Code Playgroud)
或者,更简洁,
foo(1, 2, 3, 4, 5)
# 4
foo()
# 0
Run Code Online (Sandbox Code Playgroud)
如果当然,这些函数都不执行任何类型检查,因此除非您完全信任所提供的输入,否则不要依赖这些结构的简单性.
or
工作我or
用一个人为的例子以类似的方式解释了它的工作原理.
给定定义的函数
Run Code Online (Sandbox Code Playgroud)def foo(*args): if not len(args): return 0 return max(args) - min(args)
你将如何完成
foo
返回所有数字9000
?
我们or
在这里用来处理角落的情况.我们定义foo
为:
def foo(*args):
return 0 if not args else max(args) - min(args)
Run Code Online (Sandbox Code Playgroud)
foo
在列表上执行过滤以保留所有数字9000
.如果存在任何这样的数字,列表推导的结果是一个非空的列表,它是Truthy,因此返回(这里的短路动作).如果不存在这样的数字,则列表comp的结果[]
是Falsey.因此,现在评估第二个表达式(非空字符串)并返回.
使用条件,我们可以重写这个函数,
def foo(*args):
...
Run Code Online (Sandbox Code Playgroud)
和以前一样,这种结构在错误处理方面更加灵活.
Ami*_*oki 15
引用Python文档
需要注意的是既不
and
也没有or
限制的价值和类型,他们返回False
和True
,而是返回最后一个变量.这有时是有用的,例如,如果s
是一个字符串,如果它是空的,应该用默认值替换,表达式s or 'foo'
产生所需的值.
所以,这就是Python设计用于评估布尔表达式的方法,上面的文档让我们深入了解了为什么这样做.
要获得布尔值,只需对其进行类型转换即可.
return bool(len(args) and max(args)-min(args))
Run Code Online (Sandbox Code Playgroud)
短路.
例如:
2 and 3 # Returns 3 because 2 is Truthy so it has to check 3 too
0 and 3 # Returns 0 because 0 is Falsey and there's no need to check 3 at all
Run Code Online (Sandbox Code Playgroud)
同样or
也是如此,也就是说,一旦找到它就会返回Truthy的表达式,因为评估表达式的其余部分是多余的.
而不是返回铁杆True
或者False
,巨蟒返回Truthy或Falsey,这是无论如何要评估为True
或False
.您可以按原样使用表达式,它仍然可以使用.
要知道什么是Truthy和Falsey,检查帕特里克·哈夫的答案
和/或执行布尔逻辑,但它们在比较时返回一个实际值.使用和时,从左到右在布尔上下文中计算值.布尔上下文中0,'',[],(),{}和None为false; 其他一切都是真的.
如果所有的值在布尔上下文是真实的,并且返回最后一个值.
>>> 2 and 5
5
>>> 2 and 5 and 10
10
Run Code Online (Sandbox Code Playgroud)
如果布尔上下文中的任何值为false ,则返回第一个false值.
>>> '' and 5
''
>>> 2 and 0 and 5
0
Run Code Online (Sandbox Code Playgroud)
所以代码
return len(args) and max(args)-min(args)
Run Code Online (Sandbox Code Playgroud)
返回max(args)-min(args)
有args的值返回时 返回len(args)
0.
这是合法/可靠的风格,还是有任何问题?
这是合法的,它是一个短路评估,其中返回最后一个值.
你提供了一个很好的例子.0
如果没有传递参数,函数将返回,并且代码不必检查传递的参数的特殊情况.
使用它的另一种方法是默认无参数可变基元,如空列表:
def fn(alist=None):
alist = alist or []
....
Run Code Online (Sandbox Code Playgroud)
如果传递一些非真值,alist
则默认为空列表,避免if
语句和可变默认参数陷阱的方便方法