【问题标题】:How to test equivalence of ranges如何测试范围的等价性
【发布时间】:2011-10-12 13:26:38
【问题描述】:

我的一个单元测试在读取日志文件后检查范围是否设置正确,我只想测试var == range(0,10)。但是,range(0,1) == range(0,1) 在 Python 3 中的计算结果为 False

有没有一种直接的方法来测试 Python 3 中范围的等价性?

【问题讨论】:

  • 为什么要比较两个范围?
  • 我的单元测试只是断言该范围是正确构造的。在程序中,我没有存储最小和最大可接受值,而是存储范围然后测试 val 是否在范围内。

标签: python unit-testing python-3.x


【解决方案1】:

在 Python3 中,range 返回一个 range 类型的迭代。两个ranges 相等当且仅当它们相同(即共享相同的id)。要测试其内容的相等性,请将range 转换为list

list(range(0,1)) == list(range(0,1))

这适用于短距离。对于很远的距离,Charles G Waldman's solution 更好。

【讨论】:

  • @oneporter:请注意,这会消耗迭代器,您以后将无法重新使用它。
  • @StevenRumbalski:因为range 对象是可迭代对象而不是迭代器,所以它们不能被“消费”。 You can iterate over them multiple times.
【解决方案2】:

第一个建议的解决方案 - 使用“列表”将范围转换为列表 - 效率低下,因为它会首先将范围对象转换为列表(如果范围很大,可能会消耗大量内存),然后比较每个元素。考虑例如a = 范围(1000000), “范围”对象本身很小,但是如果您将其强制到列表中,它就会变得很大。然后你必须比较一百万个元素。

答案 (2) 的效率更低,因为 assertItemsEqual 不仅会实例化列表,还会在进行元素比较之前对它们进行排序。

相反,由于您知道对象是范围,因此当它们的步幅、开始和结束值相等时它们是相等的。例如

ranges_equal = len(a)==len(b) and (len(a)==0 or a[0]==b[0] and a[-1]==b[-1])

【讨论】:

  • 如果范围步骤,这将不起作用。例如 range(1,20,2) 和 range(1,20) 是等价的。
  • 好点 krs1。我认为我的方法可以通过比较范围的 len() 来解决.... range_equal = (len(a)==len(b) and a[0]==b[0] and a[- 1]==b[-1])
  • 或者,如果避免出现空范围问题:ranges_equal = len(a)==len(b)==0 or len(a)==len(b) and a[0]==b[0] and a[-1]==b[-1]
  • 我不太确定我认为range(0,0) 一定等于range(100,100),即使两个范围都是空的。我想这取决于你对他们做了什么......
  • 嗯,对我来说,它们只是“空”的不同拼写方式。但如果这很重要,请注意所有其他建议也无法区分这些情况。如果这很重要,你可以这样做ranges_equal = str(a)==str(b)
【解决方案3】:

试试assertItemsEqual,(在docs中):

class MyTestCase(unittest.TestCase):
    def test_mytest(self):
        a = (0,1,2,3,4)
        self.assertItemsEqual(a, range(0,4))

【讨论】:

  • 请注意 assertItemsEqual 在 py3 中不可用,这是 OP 要求的。
【解决方案4】:

另一种方法:

ranges_equal = str(a)==str(b)

字符串表示表示范围的开始、结束和步长。

这个问题让我觉得也许 Python 应该提供一种从范围对象本身获取这些属性的方法!

【讨论】:

    猜你喜欢
    • 2011-12-15
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 2022-04-27
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    相关资源
    最近更新 更多