在检查了几个python开源项目之后,我发现了一些示例,其中相同的功能具有assert <>
和assert <> is True
的测试用例。
我找不到有关在有条件或无条件的情况下使用assert
语句的最佳实践的答案。
例如功能
def is_even(number):
if number % 2 == 0:
return True
else:
return False
可以通过这种方式进行测试
assert is_even(6) is True
assert is_even(6) == True
但也可以像
那样进行测试assert is_even(6)
在这里我看到问题原因,如果函数is_even
将被更改
def is_even(number):
if number % 2 == 0:
return <>
else:
return False
<>
可以更改为任何数字(0
除外)或非空字符串的地方-最后一次测试将通过。但这将是另一个功能。
我看到this和this这样的关于断言用法的问题,但似乎它们并未完全涵盖我的问题。
PEP 8 specification从另一面来看
请勿使用==
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
但这还与assert
的使用有关吗?
答案 0 :(得分:4)
类似的代码
if a:
return True
else:
return False
还是不干净。应该将其写为return a
,或者,如果需要布尔值(而不仅仅是一个稳定值),则应return bool(a)
。
如果您使用v == True
或v is True
完全取决于情况。第一个将检查值是否等于值True
。一个值是否执行此操作,也取决于该值的类别(例如,1 == True
为true,1.0 == True
为true,但是1j == True
为false)。
如果您使用is
进行比较,那么您绝对清楚地接受了值True
,而没有其他东西。
但是,在大多数情况下,我认为仅声明assert f(x)
是在语义上正确的事情。例如,像assert is_in_rectangle(point)
这样的断言。将其拼写为assert is_in_rectangle(point) == True
或assert is_in_rectangle(point) is True
是错误的,因为任何隐含值(例如[ 1 ]
)都足够。如果检查结果是否为显式True
,则假设结果过多。
因此,基线:不要将真实值与True
进行比较。如果您对值的要求非常明确,例如“必须是布尔值,而不仅仅是行情波动”(这是极少数情况),则仅将结果值与True
进行比较。
答案 1 :(得分:2)
assert
完全像 if
。它是一个关键字,后跟一个布尔表达式,它要求该表达式的计算结果为True
。 assert expression
仅在if expression
成功的情况下才会成功。
鉴于此,您的问题有两个方面。前condition
和condition==True
。这是风格问题。您无需写if condition==True:
,而只需写if condition:
。同样,没有理由写
assert is_even(6) == True
只要写
assert is_even(6)
相反。
第二个是condition==True
对condition is True
。这不仅仅是样式问题。运行以下
if []==False: # also: if not []
print('false')
if bool([]) is False:
print('false')
if [] is False:
print('false')
将打印示例(1)和(2),但不会打印示例(3)。
False
是一个单例值,表示python解释器中只有一个 False
对象,而所有错误的对象是< em>同一个对象。因此,使用is
感觉不错(就像写if object is None
被认为是一种好风格一样)。但是,python中存在虚假/真实值的概念:如果if condition
为假,condition
不一定为bool(condition)
,但不一定触发。这是自动完成的。在上面的示例中,空列表是虚假值。即bool([])
的计算结果为False
对象(同样,它只是一个)。因此,示例(1)成功,因为它已自动(内部)转换为类似于示例(2)的内容。但是,示例(3)不起作用,因为尽管空列表评估为false ,但并非 False
。这是一个空列表。所以,总结一下例子
if greeting: # good style, and it works
if greeting==True: # bad style, redundant, but it still works
if greeting is True: # misleading. does a different thing than it seems to do. avoid it
结束语:您给出示例
def is_even(number):
if number % 2 == 0:
return <>
else:
return False
您提到<>
可能是任何真实值。本着这种精神,相当于写
def is_even(number):
return number % 2
因为它将返回非零(真实)或零(虚假)。但是,不要这样做。函数is_even
的用户希望函数返回True
或False
,而不是整数。您不知道该用户如何使用您的代码(例如,可能会将其发送到期望真正布尔值的数据库或Web服务)。因此,最好返回一个布尔值。因此,该函数最短最安全的形式就是编写
def is_even(number):
return bool(number % 2)