断言和测试迭代的空虚

时间:2016-12-22 16:48:07

标签: python assert truthiness

使用内置的assert语句,是否有一种很好的Pythonic方法可以检测迭代中的空虚?我见过:

但我正在寻找使用断言的解决方案。以下看起来可以工作,但我不确定我是否遗漏了一些重要的可能异常:

a = [1, 2, 3]
b = []

assert a, 'a is empty'
assert b, 'b is empty'

提出此AssertionError

Traceback (most recent call last):
  File "<ipython-input-9-185714f6eb3c>", line 5, in <module>
    assert b, 'b is empty'
AssertionError: b is empty

2 个答案:

答案 0 :(得分:4)

请记住,不要将container(思考列表,集合,元组,词典,等等)与iterable混淆(任何可能出现新状态的东西)。检查iterable是否为空的唯一方法是#34;是尝试迭代它并找出它是否不会产生至少一个新状态。您可以自由地将其解释为iterable正在&#34;空&#34;。

像这样的东西

def test_thing_is_empty(self):  # We are in a unittest.Testcase
    foo = iter([])  # Or any other iterable thing
    try:
        item = next(foo)
    except StopIteration:
        pass  # This is what should happen
    else:
        self.fail("Expected foo to be empty, got %s" % (item, ))

还要记住,iterable在技术上从来都不是真正的#34;空的&#34;。尽管不鼓励,但有时允许iterable抛出一个StopIteration,如果再次尝试,所有突然开始产生新元素。

因此无法assert这个。你必须试着看看你是否失败了。如果你失败了,唯一真正的知识是iterable现在没有产生新的状态(无论出于何种原因)。如果你得到一个项目,iterable只会产生一个独特的,珍贵的雪花,可能永远不会再次重现(想想从堆栈中某处的网络插座读取)。

答案 1 :(得分:-2)

怎么样:

assert len(a), "a is empty"

它与assert a, ...listdict对象的set效果相同,但您可能会发现它看起来更清晰/更易于维护。

assert a, ...assert len(a), ...都不能保证适用于任意迭代,但您可能会发现后者更可取,因为它会抛出没有{{的迭代的异常1}},而不是让断言通过假阳性。看起来没有完全通用的解决方案(即你无法构建一个可以打败它的迭代的解决方案)。