【问题标题】:Use cases for "and" in variable assignment变量赋值中“and”的用例
【发布时间】:2020-01-08 11:07:13
【问题描述】:

我今天发现你可以在变量赋值中使用and,类似于使用or。我很少遇到以这种方式使用or,但从未听说过有人以这种方式使用and。这是否过于晦涩难懂,无法推荐使用,还是有一些具体的用例有助于提高代码的清晰度或简洁性?

a = 1
b = 3
# c is equal to b unless a or b is False; then c is equal to the "False" value. False may be 0, [], False, etc.
c = a and b
print(f'a = {a}, b = {b}, c = {c}')
>>>a = 1, b = 3, c = 3

d = 1
e = 5
# f is equal to d unless d is False; then f is equal to e. Again, "False" may be 0, [], False, etc.
f = d or e
print(f'd = {d}, e = {e}, f = {f}')
>>>d = 1, e = 5, f = 1

似乎有一个奇怪的不一致之处,显然可以使用运算符来评估条件并将变量设置为该条件的真实性(例如g = h > ij = k is l 等)。

不过,and 似乎是个例外。不是评估赋值的条件权,而是根据上面注释中描述的规则分配变量。为什么 c = a and b 不只评估为 TrueFalse 取决于 ab 具有真实值? (上面的例子将评估为True

谢谢

【问题讨论】:

标签: python python-3.x variable-assignment


【解决方案1】:

您的问题:为什么 c = a 和 b 不只是根据 a 和 b 的真实值来评估为 True 或 False?

根据Python手册,a and b的定义是:

if a is false, then a, else b

所以在您的特定情况下a 没有副作用时,上面翻译成实际的Python 将相当于:

c = a if not a else b

a 没有副作用通常不是真的。所以c = a and bc = a if not a else b的区别如下:

  1. 对于a and b,如果a 为真,则永远不会评估b,而a 只会评估一次。

  2. 对于c = a if not a else b,和以前一样,如果a 为真,则永远不会评估b,但将再次评估a,如果a 确实有边,这可能是一个问题效果。

【讨论】:

    【解决方案2】:

    如前所述,基本上这里发生的是短路评估。当and 中的第一个值计算为True 时,它返回第二个值,而不是返回False 值。考虑这些陈述

    >>> 1 and 0
    0
    >>> 1 and 3
    3
    >>> 0 and 1
    0
    >>> False and "Text"
    False
    "Text" and False
    False
    

    【讨论】:

      【解决方案3】:

      使用and 进行短路是用很少的代码表达您的意图的便捷方式(确实是一个理想的目标)。

      考虑这个初始化,如果不知道user 是非空的,你必须做什么。

      name = user and user.name
      

      当然,三元组是一个类似的单线器

      name = user.name if user else None
      

      但它有那么可读吗?

      最后,当使用短路 and 链接多个 getter 时,真正开始节省您的理智。

      coords = user and user.location and user.location.coords
      

      当您确定覆盖虚假值不会有问题时,使用or 而非None 提供更好的默认值。

      name = user and user.name or 'Unnamed'
      

      【讨论】:

      • 你值得拥有很棒的道具!
      • 当您像第三个和第四个示例一样将它们链接在一起时,操作顺序是如何工作的?谢谢
      • @HoboProber 您可以使用print 来查看评估的顺序,例如:(not print(1)) and print(2) or print(3)。注意print 返回None,所以not print(1)True
      • 就我个人而言,我发现它更难阅读,尤其是调试或处理异常。我更喜欢明确的代码,结合guard clauses,这在所有这些方面都更容易:if user is None: return; if user.location is None: return; process(user.location.coords),根据您的需要,“return”也可以是“raise”、“break”、“continue”等。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-04
      • 2016-09-21
      • 2020-02-21
      • 1970-01-01
      相关资源
      最近更新 更多