Python 'and/or' 在表达式中是什么意思,`(not i%2)` 测试什么?

Python what do 'and/or' mean in expression, and what does `(not i%2)` test?

我正在学习python list comprehension 并看到一个用法,但我在官方文档中找不到解释。

>>>[(not i%2)*'a' or str(i) for i in range(10)]
>>>['a', '1', 'a', '3', 'a', '5', 'a', '7', 'a', '9']

我试图以这种方式抽象这种用法:

[statement1 or statement2 for i in range(10)]

如果 statement1 被评估为 false,那么使用 statement 2,对吗?

我还发现,如果我 运行 以下命令:

>>> [(not i%2)*'a' and str(i) for i in range(10)]

输出将是:

>>> ['0', '', '2', '', '4', '', '6', '', '8', '']

这些应该怎么理解?

没错。奇怪的部分是第一个表达式:

(not i%2)*'a'

如果 i 是奇数,则计算结果为 'a';如果偶数,则为 False。这是对 Python.

中布尔定义的公然滥用(a.k.a。专家技巧)

如果您将 True 想象为 1,将 False 想象为 0,这是有道理的。如果乘积为 0,则 or 运算符将其视为 False

这也利用了表达式短路:如果 or 的左边元素是 True,那么右边的元素就是' 完全计算,左边的元素成为表达式的值。

同样,在您后面的示例中,and 短路以另一种方式工作:如果左侧元素为 False,则它成为结果;否则,正确的元素成为结果。

此处或 return 第一个可以计算为 True 的值。 所以如果第一个语句 return 值可以被评估为 True,就使用它或搜索下一个值。 尝试添加更多 'or'

 [(not i%3)*'a' or (not i%5)*'b'  or 'c' for i in range(10)]
 => ['a', 'c', 'c', 'a', 'c', 'b', 'a', 'c', 'c', 'a']

和return仅当所有值都可以计算为True

时才是最后一个值

声明解释:

not i%2:对于偶数,i % 2 的计算结果为 0,对于奇数的计算结果为 1not 将产生一个否定以下表达式的布尔值。 not 1 => False, not 0 => True.

(True)*'a' => 1 * 'a' => 'a'

(False)*'a' => 0 * 'a' => ''

'',当转换为布尔值时,计算为 False

False or str(i) => str(i)

如果将其转换为元组列表(包括两个条件),则更容易看出发生了什么:

>>> [((not i%2)*'a', str(i)) for i in range(10)]
[('a', '0'), ('', '1'), ('a', '2'), ('', '3'), ('a', '4'), ('', '5'), ('a', '6'), ('', '7'), ('a', '8'), ('', '9')]

i 的任何奇数值都会产生 '',即 Python 意义上的 False。然后 or 计算右侧,returns 而不是左侧:

>>> 'LH' or 'RH'
'LH'
>>> '' or 'RH'
'RH'

更好表示为条件表达式,因为它更易于阅读:

>>> ['a' if i%2==0 else str(i) for i in range(10)]
['a', '1', 'a', '3', 'a', '5', 'a', '7', 'a', '9']