【问题标题】:Is OR and ELSE similar in list comprehension statement列表理解语句中的 OR 和 ELSE 是否相似
【发布时间】:2018-01-25 23:11:19
【问题描述】:

请帮助我了解为什么会这样。下面的代码列出了迭代中的重复项。但是,使用 or 运算符的行为类似于 if..else 语句中的 else..

j = set()
my_list = [1, 2, 3 ,3 , 3 ,4, 4]
j_add = j.add
twice = set(x for x in my_list if x in j or j_add(x))
print list(twice)

希望该行是:

 twice = set(x for x in my_list if x in j else j_add(x))

思考或返回布尔值而不是值

【问题讨论】:

  • 从技术上讲,你没有列表理解,你有一个生成器表达式。
  • 不,or 不是else 语句。这是测试的一部分。您可以在任何ifwhile 语句中使用相同的布尔表达式。 or 短路,如果左边的表达式产生一个真值,它将不会执行右边的表达式。
  • 谢谢..目标不是删除重复项,而是捕获它们。上面的代码在执行时会返回[3, 4]。
  • 对,如果您想捕获多次出现的项目,请使用Counter() 并过滤结果计数。这会导致代码更简洁。
  • 我通常反过来说。试试这个:两次 = set(x if x in j else j_add(x) for x in my_list)

标签: python python-2.7 generator-expression


【解决方案1】:

or 运算符返回最后评估的参数,它可能是也可能不是布尔值。

Documentation 中解释了此行为:

请注意,andor 都不会限制它们返回到 FalseTrue 的值和类型,而是返回最后评估的参数。这有时很有用,例如,如果 s 是一个字符串,如果它是空的,则应该将其替换为默认值,则表达式 s or 'foo' 会产生所需的值。

当然,记住什么被解释为假,什么被解释为真会有所帮助:

[T]以下值被解释为假:FalseNone、所有类型的数字零以及空字符串和容器(包括字符串、元组、列表、字典、集合和冻结集)。所有其他值都被解释为 true。

所以在表达式中:

A = B or C

正如@MartijnPieters 在评论中指出的那样,or 表达式短路。如果第一个参数(在这种情况下为B)被解释为真,则整个表达式必须为真,因此第二个参数(C)永远不会被计算。因此,第一个参数 (B) 是“最后评估的参数”并且是返回的内容。但是,如果第一个参数 (B) 被解释为 false,则仍必须评估第二个参数 (C) 以确定表达式的真实性(不会发生短路)。在这种情况下,“最后计算的参数”是第二个参数 (C),无论表达式的计算结果是真还是假,都会返回它。

有效地完成了与Conditional Expression相同的工作:

A = B if B else C

但是,条件表达式仅在 2.5 版中添加到 Python 中,而布尔运算符行为从一开始就存在(或至少存在很长时间)。大多数经验丰富的 Python 程序员会很容易识别并习惯使用A = B or C。条件表达式通常保留用于更复杂的条件,这些条件不适用于简单的or(例如,在A = B if X else C 中,条件不是基于B 而是X 的真实性,这可能是来自复杂表达式的简单值)。

但是,您需要小心,因为正如 JaredGoguen 在他的回答中指出的那样,将 OP 示例中的 or 更改为 else 实际上会改变代码的行为。该代码的编写取决于or 运算符的这种特定行为。您不能只用条件表达式替换任何使用 or 进行赋值的操作。可能还需要额外的重构。

【讨论】:

    【解决方案2】:

    我可能在这里做一个价值判断,说这不是好的代码,因为它使用了or 的短路行为来产生副作用。

    考虑给定的条件:if x in j or j_add(x)

    x in j 时,or 短路,跳过条件的j_add(x) 部分,并计算为True

    x not in j 时,检查声明j_add(x) 的真实性。此方法返回 None,这是假的,因此 or 评估为 False

    因此,整个条件的计算结果与x in j 相同。但是j_add(x) 的副作用是将x 添加到j!正在利用这种副作用来记录唯一​​成员my_list,以便快速理解。

    or 更改为else 仍会根据需要构造j,但会不恰当地将Nonej_add(x) 的返回值)添加到twice

    【讨论】:

      猜你喜欢
      • 2018-12-15
      • 1970-01-01
      • 1970-01-01
      • 2020-05-13
      • 2020-02-29
      • 2019-11-24
      • 2022-12-10
      • 1970-01-01
      • 2018-09-08
      相关资源
      最近更新 更多