【问题标题】:Comparison in Python assert statement [duplicate]Python断言语句中的比较[重复]
【发布时间】:2018-10-08 10:47:55
【问题描述】:

在检查了几个 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

&lt;&gt; 可以更改为任何数字(0 除外)或非空字符串 - 最后一次测试将通过。但这将是另一个功能。

我看到了 thisthis SO 关于断言用法的问题,但似乎它们并没有完全涵盖我的问题。

从另一边 PEP 8 specification 有这样的例子

  • 不要使用 == 将布尔值与 True 或 False 进行比较

    Yes:   if greeting:
    No:    if greeting == True:
    Worse: if greeting is True:
    

但这也与assert 的使用有关吗?

【问题讨论】:

  • 是的,关于布尔值的 PEP-8 建议也适用于 assert 的用法。同样,该函数应写为:def is_even(number):return number % 2 == 0
  • 你到底在问什么?
  • @DeepSpace 的问题是仅使用assert is_even(6) 或更好地使用assert is_even(6) is True 进行测试是一种好习惯,因为可以更改功能并且assert 也将通过,但这将是另一个函数(将返回另一个结果)
  • 还要注意assert 经常被误用,它应该只用于健全性检查(应该不可能的事情),你应该raise 一个例外,比如输入错误数据
  • PEP-8 在这一点上非常清楚不要使用 == 将布尔值与 True 或 False 进行比较。。您在哪里执行此操作并不重要。这些示例使用if,但这并不重要。该断言适用于任何上下文。测试是针对ifassertwhile、条件表达式还是作为其结果存储在变量中的独立表达式完成并不重要。

标签: python assert assertion


【解决方案1】:

类似代码

if a:
    return True
else:
    return False

反正是不干净的。它应该写成return a,或者,如果需要一个布尔值(而不仅仅是一个真值),则应该写成return bool(a)

如果您使用v == Truev is True,则完全取决于情况。第一个将检查值是否等于True。一个值是否这样做,也取决于这个值的类(例如1 == True 为真,1.0 == True 为真,但1j == True 为假)。

如果您使用is 进行比较,那么您绝对清楚地表明您接受True 的值而不是其他值。

然而,在大多数情况下,我认为仅声明 assert f(x) 是语义上正确的做法。例如对于像assert is_in_rectangle(point) 这样的断言。将其拼写为assert is_in_rectangle(point) == Trueassert is_in_rectangle(point) is True 是错误的,因为任何真实值(例如[ 1 ])就足够了。检查明确的True 结果会假设太多。

因此,基线:不要将真实值与True 进行比较。如果您对值有非常具体的要求,例如“必须是布尔值,而不仅仅是真实”(这种情况很少见),则仅将结果值与 True 进行比较。

【讨论】:

    【解决方案2】:

    assert 一模一样 if。它是一个关键字,后跟一个布尔表达式,它要求表达式的计算结果为True。语句assert expression 将成功当且仅当if expression 成功。

    鉴于此,您的问题有两个方面。第一个 conditioncondition==True。这是风格问题。你不写if condition==True:,而只是写if condition:。同样,没有理由写

    assert is_even(6) == True
    

    随便写

    assert is_even(6)
    

    改为。

    第二个是condition==True vs 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对象,所有的假对象都是一样的对象。所以,使用is 感觉不错(就像写if object is None 被认为是好的风格一样)。但是,python 中有 falsy/truthy 值的概念:if condition 不一定会在 condition 为 false 时触发,但在 bool(condition) 为 false 时触发。这是自动完成的。在上面的例子中,空列表是一个假值。那就是 bool([]) 评估为 False 对象(同样,它只是一个)。因此,示例 (1) 成功,因为它会自动(内部)转换为示例 (2) 之类的内容。但是,示例 (3) 不起作用,因为尽管空列表 评估为假,但它不是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
    

    您提到&lt;&gt; 可能是任何真实值。本着这种精神,就相当于写了

    def is_even(number):
         return number % 2
    

    因为它会返回非零(真实)或零(虚假)。但是,不要那样做。名为is_even 的函数的用户期望该函数返回TrueFalse,而不是整数。您不知道该用户如何使用您的代码(例如,可能将其发送到数据库或需要真正布尔值的 Web 服务)。所以最好返回一个布尔值。因此,函数的最短和最安全的形式是编写

    def is_even(number):
        return bool(number % 2)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-30
      • 2021-01-21
      • 2018-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多