列表理解语句中的 OR 和 ELSE 是否相似
Is OR and ELSE similar in list comprehension statement
请帮助我理解为什么会这样。下面的代码列出了可迭代对象中的重复项。但是,使用 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))
想法或 returns 布尔值而不是值
or
运算符 returns 最后计算的参数,可能是也可能不是布尔值。
此行为在 Documentation:
中进行了解释
Note that neither and
nor or
restrict the value and type they return to False
and True
, but rather return the last evaluated argument. This is sometimes useful, e.g., if s
is a string that should be replaced by a default value if it is empty, the expression s or 'foo'
yields the desired value.
当然,记住什么被解释为假,什么被解释为真会有所帮助:
[T]he following values are interpreted as false: False
, None
, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as true.
所以在表达式中:
A = B or C
正如@MartijnPieters 在评论中指出的那样,or
表达式短路。如果第一个参数(在本例中为 B
)被解释为真,则整个表达式必须为真,因此第二个参数(C
)永远不会被计算。因此第一个参数 (B
) 是 "the last evaluated argument" 并且是返回的内容。但是,如果第一个参数 (B
) 被解释为 false,则仍必须评估第二个参数 (C
) 以确定表达式的真实性(不会发生短路)。在这种情况下,"the last evaluated argument" 是第二个参数 (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
的任何使用。可能还需要额外的重构。
我可能会在这里做一个价值判断,说这不是好的代码,因为它利用了or
的短路行为来产生副作用。
考虑给定的条件:if x in j or j_add(x)
.
当x in j
时,or
短路,跳过条件的j_add(x)
部分,求值为True
.
当 x not in j
时,将检查语句 j_add(x)
的真实性。此方法 returns None
,它是假的,因此 or
评估为 False
.
因此,整个条件的计算结果与 x in j
相同。然而 j_add(x)
有将 x
添加到 j
的副作用!正在利用此副作用来记录唯一成员 my_list
快速理解。
将 or
更改为 else
仍会根据需要构造 j
,但会不恰当地添加 None
,return 的值 j_add(x)
, 至 twice
.
请帮助我理解为什么会这样。下面的代码列出了可迭代对象中的重复项。但是,使用 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))
想法或 returns 布尔值而不是值
or
运算符 returns 最后计算的参数,可能是也可能不是布尔值。
此行为在 Documentation:
中进行了解释Note that neither
and
noror
restrict the value and type they return toFalse
andTrue
, but rather return the last evaluated argument. This is sometimes useful, e.g., ifs
is a string that should be replaced by a default value if it is empty, the expressions or 'foo'
yields the desired value.
当然,记住什么被解释为假,什么被解释为真会有所帮助:
[T]he following values are interpreted as false:
False
,None
, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as true.
所以在表达式中:
A = B or C
正如@MartijnPieters 在评论中指出的那样,or
表达式短路。如果第一个参数(在本例中为 B
)被解释为真,则整个表达式必须为真,因此第二个参数(C
)永远不会被计算。因此第一个参数 (B
) 是 "the last evaluated argument" 并且是返回的内容。但是,如果第一个参数 (B
) 被解释为 false,则仍必须评估第二个参数 (C
) 以确定表达式的真实性(不会发生短路)。在这种情况下,"the last evaluated argument" 是第二个参数 (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
的任何使用。可能还需要额外的重构。
我可能会在这里做一个价值判断,说这不是好的代码,因为它利用了or
的短路行为来产生副作用。
考虑给定的条件:if x in j or j_add(x)
.
当x in j
时,or
短路,跳过条件的j_add(x)
部分,求值为True
.
当 x not in j
时,将检查语句 j_add(x)
的真实性。此方法 returns None
,它是假的,因此 or
评估为 False
.
因此,整个条件的计算结果与 x in j
相同。然而 j_add(x)
有将 x
添加到 j
的副作用!正在利用此副作用来记录唯一成员 my_list
快速理解。
将 or
更改为 else
仍会根据需要构造 j
,但会不恰当地添加 None
,return 的值 j_add(x)
, 至 twice
.