哪个是#34;更正确(逻辑上)"? 特定于闰年,而不是一般。
使用括号
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
没有
return year % 4 == 0 and year % 100 != 0 or year % 400 == 0
其他信息
圆括号改变了评估布尔值的顺序(and
在or
括号之前“。
鉴于此问题中所有较大的数字都可以被较小的数字整除,它会以任何方式返回正确的结果,但我仍然很好奇。
观察括号的影响:
False and True or True
#True
False and (True or True)
#False
False and False or True
#True
False and (False or True)
#False
如果没有括号,有些情况下即使年不能被4整除(第一个bool),它仍然会返回True (我知道在这个问题上不可能)! 不能被4整除,因此包括括号更正确吗?我还应该注意什么?有人可以解释不包括括号的理论逻辑吗?
答案 0 :(得分:5)
parens影响你的布尔人采取的顺序。在and
之前,or
被组合在一起并得到解决,因此:
a and b or c
变为:
(a and b) or c
如果a
和b
两者都是真实的,或者c
是真的,我们会True
。
用括号得到:
a and (b or c)
现在,如果True
两者都是真实的,a
或b
是真的,那么你会得到c
。
就“正确性”而言,只要您的代码得出正确的结果,那么“更正确”只是意见问题。我会在你认为结果更清晰的地方加入parens。例如:
if (a and b) or c:
比
更清晰if a and b or c:
然而,(在我看来)并不比以下更清楚:
if some_long_identifier and some_other_long_identifier or \
some_third_long_identifier_on_another_line:
编写Python代码时,您的指南应为PEP8。当你应该包括风格括号时,PEP8很安静(阅读:遵循自然操作顺序的parens),所以请用你最好的判断。
具体来说,闰年的逻辑是:
换句话说:所有可被4整除的年份都是闰年,除非它们可被100整除且不能被400整除,这意味着:
return y % 4 == 0 and not (y % 100 == 0 and y % 400 != 0)
答案 1 :(得分:3)
包括括号。在英语中,规则是:
带括号的版本最符合这个双管齐下的规则。
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(1) (2)
实际上,删除括号不会破坏代码,但会导致规则的不自然版本:
这不是我对闰年规则的看法。
答案 2 :(得分:1)
答案:包含括号
John Kugelman解释了为什么它们是2个单独的逻辑测试而不是3个, - >最后2个应该组合在一起:
带括号的版本最符合这个双管齐下的规则。
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(1) (2)
实际上,删除括号不会破坏代码,但会导致规则的不自然版本:
这不是我对闰年规则的看法。
受mrdomoboto的启发,100/400是例外!:
年份必须可以被4 整除,100是例外,400是例外,但它们仍然是一个例外(见上文)。这意味着如果年份不能被4整除,则整个事物必须为假。确保这一点的唯一方法是将异常放在异常周围,因为False and bool
将始终返回False。
请参阅以下JBallin
的示例False and True or True
#True
False and (True or True)
#False
False and False or True
#True
False and (False or True)
#False
Adam Smith将英语翻译成代码:
所有可被4整除的年份都是闰年,除非它们可以被100整除而不能被400整除,这意味着:
return y % 4 == 0 and not (y % 100 == 0 and y % 400 != 0)
not(a and b) = (not a or not b)
要将上述内容转换为所需的答案:
#convert using "DML"
return y % 4 == 0 and (not y % 100 == 0 or not y % 400 != 0)
#remove "not"s by switching "==" and "!="
return y % 4 == 0 and (y % 100 != 0 or y % 400 == 0)
答案 3 :(得分:1)
这是另一个区别:速度和效率。
除了评估顺序(已在其他答案中提及)...
让我们简化原始表达
year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
:
A and (B or C)
如果A
为假,则没有理由测试B
或C
,因为and
要求两面都为true
。
短路电路操作员
逻辑运算符and
和or
在包括Python在内的许多语言中都具有“短路”效应,其中仅对左侧求值(请参见https://docs.python.org/2/library/stdtypes.html#boolean-operations-and-or-not):
and
在左侧为false
时发生短路(因为右侧不能使结果为true
)or
在左侧为true
时发生短路(因为右侧不能使结果为false
)具有监护功能:
A and (B or C)
A
为false
时,右侧(B or C)
不会得到评估,从而节省了CPU资源。A
为true
时,B
得到评估,但是C
仅在B
为假时才得到评估。完全没有心态:
A and B or C
A
为false
时,B
不会得到评估,但是C
得到(不必要)会得到评估。A
为true
时,B
得到评估。如果B
是false
,则C
也将得到评估。 结论:
如果没有括号,则C
为假(year % 400
测试)时,A
(year % 4
测试)将得到不必要的评估。这是CPU可以在A
处停止的时间的75%,但继续执行不必要的数学运算。
最有效的表达方式
改为使用此:
((year & 3) == 0 && ((year % 25) != 0 || (year & 15) == 0))
在两种情况下,该表达式用按位与(快速!)替换模(慢除)。
更多详细信息,请访问:https://stackoverflow.com/a/11595914/733805