“and”和“and”或“or”如何处理非布尔值?

我正在尝试学习python,并且遇到了一些代码,这些代码很好,很短,但没有完全意义

背景是:

def fn(*args):
返回len(args)和max(args)-min(args)

我知道它在做什么,但是python为什么要这样做——即返回值而不是True/False

10和7-2

返回5。类似地,将and更改为or将导致功能更改。所以

10或7-2

我将返回10

这是合法/可靠的风格,还是有什么问题

TL;DR

我们首先总结两个逻辑运算符的两种行为。这些习语将构成我们下面讨论的基础

返回第一个Falsy值(如果有),否则返回最后一个
表达式中的值

返回第一个真实值(如果有),否则返回最后一个真实值
表达式中的值

这些行为也在文件中进行了总结,特别是在下表中:

唯一返回布尔值的运算符(无论其操作数是什么)是not运算符


&引用;“真实性”;,及;“真实的”;评价

声明

len(args)和max(args)-min(args)

是一种非常pythonic的简洁(而且可以说不那么可读)的表达方式;如果args不为空,则返回max(args)-min(args)的结果;,否则返回0。一般来说,它是if-else表达式的更简洁的表示形式。比如说,

exp1和exp2

应(大致)转化为:

r1=exp1
如果r1:
r1=exp2

或者,相当于

r1=exp2如果exp1其他exp1

同样地

exp1或exp2

应(大致)转化为:

r1=exp1
如果不是r1:
r1=exp2

或者,相当于

r1=exp1如果exp1其他exp2

其中exp1exp2是任意python对象,或返回某个对象的表达式。理解逻辑运算符用法的关键在于理解它们不限于对布尔值进行操作或返回布尔值。任何具有真实性值的对象都可以在此处进行测试。这包括intstr列表dict元组集合非类型,以及用户定义的对象。短路规则仍然适用

但什么是真实性?
它指在条件表达式中使用对象时如何求值@Patrick Haugh在这篇文章中很好地总结了真实性

所有值均被视为“值”;“真实的”;除了以下几点,它们是
&引用;“法尔西”:

  • None
  • False
  • 0
  • 0.0
  • 0j
  • Decimal(0)
  • 分数(0,1)
  • []-空的列表
  • {}-一个空的dict
  • ()-空的元组
  • '-一个空的str
  • b'-一个空的字节
  • set()-空的set
  • 空的范围,如范围(0)
  • 对象的
    • obj.\uuubool\uuuu()返回False
    • obj.\uuu len\uuu()返回0

A「;“真实的”;值将满足ifwhile
声明。我们使用;“真实的”;及;“法尔西”;区别于
boolTrueFalse


的工作原理

我们以OP的问题为基础,继续讨论这些操作符在这些情况下是如何工作的

给定一个定义为

def foo(*args):
...

如何返回最小值和最大值之间的差值
在零个或多个参数的列表中

找到最小值和最大值很容易(使用内置函数!)。这里唯一的障碍是正确处理参数列表可能为空的情况(例如,调用foo())。由于运算符,我们可以在一行中同时执行这两项操作:

def foo(*args):
返回len(args)和max(args)-min(args)
foo(1,2,3,4,5)
# 4
foo()
# 0

由于使用了,如果第一个表达式为,则还必须计算第二个表达式。请注意,如果第一个表达式的计算结果为truthy,则返回值始终为第二个表达式的结果。如果第一个表达式的计算结果为Falsy,则返回的结果是第一个表达式的结果

在上面的函数中,如果foo接收到一个或多个参数,len(args)大于0(一个正数),则返回的结果是max(args)-min(args)。OTOH,如果没有传递任何参数,len(args)0,这是错误的,并且返回0

请注意,编写此函数的另一种方法是:

def foo(*args):
如果不是len(参数):
返回0
返回最大值(args)-最小值(args)

或者更简单地说

def foo(*args):
如果不是参数,则返回0,否则最大值(参数)-最小值(参数)

当然,如果这些函数都不执行任何类型检查,那么除非您完全信任提供的输入,不要依赖这些结构的简单性


的工作原理

以类似的方式使用代码的例子

给定一个定义为

def foo(*args):
...

您如何填写foo以返回超过9000的所有数字

我们使用来处理这里的拐角情况。我们将foo定义为:

def foo(*args):
返回[x表示参数中的x,如果x>9000]或“没有超过9000的数字!”
傅(9004,1,2500)
# [9004]
foo(1,2,3,4)
#“不超过9000!”

foo对列表执行过滤,以保留9000上的所有数字。如果存在任何这样的数字,列表理解的结果是一个非空的列表,它是真实的,因此它被返回(在这里短路)。如果不存在这样的数字,则列表comp的结果是[],这是错误的。因此,现在对第二个表达式求值(非空字符串)并返回

使用条件,我们可以将这个函数重写为

def foo(*args):
r=[x表示参数中的x,如果x>9000]
如果不是r:
返回“不超过9000!”
返回r

与以前一样,这种结构在错误处理方面更加灵活

发表评论