如何“与"和“或"使用非布尔值? [英] How do "and" and "or" act with non-boolean values?

查看:90
本文介绍了如何“与"和“或"使用非布尔值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习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

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

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

其中exp1exp2是任意的python对象,或返回某些对象的表达式.理解逻辑andor运算符的用法的关键在于理解它们不限于对布尔值进行操作或返回布尔值.任何具有真实性值的对象都可以在此处进行测试.这包括intstrlistdicttuplesetNoneType和用户定义的对象.短路规则也同样适用.

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 empty list
    • {} - an empty dict
    • () - an empty tuple
    • '' - an empty str
    • b'' - an empty bytes
    • set() - an empty set
    • an empty range, like range(0)
    • objects for which
      • obj.__bool__() returns False
      • obj.__len__() returns 0

      真实"值将满足由ifwhile执行的检查 陈述.我们使用真实"和虚假"来区别于 boolTrueFalse.

      A "truthy" value will satisfy the check performed by if or while statements. We use "truthy" and "falsy" to differentiate from the bool values True and False.


      and的工作方式

      我们以OP的问题为切入点,讨论了在这些情况下如何使用这些运算符.


      How and Works

      We 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 the and 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 is True. 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 than 0 (a positive number), so the result returned is max(args) - min(args). OTOH, if no arguments are passed, len(args) is 0 which is Falsy, and 0 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 over 9000?

      我们在这里使用or处理拐角处的情况.我们将foo定义为:

      We use or to handle the corner case here. We define foo 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 over 9000. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆