我正在学习python列表理解,看到一个用法,但在官方文档中找不到解释。
>>>[(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', '']
我应该如何理解这些?
没错。奇怪的部分是第一个表达式:
(不是我% 2)* a
如果i是奇数,则this的求值为'a';如果是偶数,则为False。这是对Python中布尔定义的公然滥用(又名专家技巧)。
如果将True想象为1,False为0,这是有意义的。如果乘积为0,或运算符将其作为False。
还利用了表达式短路的优点:如果或的左侧元素为True,则根本不计算右侧元素,而左侧元素成为表达式的值。
类似地,在后面的例子中,和短路以另一种方式工作:如果左侧元素为False,则它成为结果;返回第一个可以计算为True
的值。因此,如果第一个语句的返回值可以计算为True,就使用它或搜索下一个值。尝试添加更多的"或"
[(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']
并且只有当所有值都可以求值为True
语句说明:
not i%2
: i % 2
对偶数求0
,对奇数求1
。not
将产生一个布尔值,对下面的表达式求反。not 1
=> False
, and 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
计算右侧,并返回右侧,而不是左侧:
>>> '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']