python __eq__ 测试失败
Posted
技术标签:
【中文标题】python __eq__ 测试失败【英文标题】:python failing __eq__ test 【发布时间】:2020-01-28 20:05:59 【问题描述】:我是 python 新手,正在学习使用 pytest
。我有一个类定义为:
class Matrix:
def __init__(self, *rows):
row_length = len(rows[0])
for row in rows:
# TODO skip first
if len(row) != row_length:
raise SystemError("Rows does not have equal length")
self._rows = [*rows]
def __eq__(self, other):
return isinstance(self, other.__class__) and \
all([x == y for x, y in zip_longest(self._rows, other._rows)])
# other methods omitted for simplicity...
我为__eq__(self, other)
写了一个测试,如下所示:
def test_eq():
m1 = Matrix([[1,2,3],[4,5,6]])
m2 = Matrix([1,2,3],[4,5,6])
m3 = Matrix([1,2,3],[5,4,6])
assert m1 == m2
assert m2 == m1
assert m2 != m3
Wich 应该通过,因为 m1
和 m2
具有相同的行,而 m3
在第二行中存在差异。但是,当我运行此测试时,我有输出:
def test_eq():
m1 = Matrix([[1,2,3],[4,5,6]])
m2 = Matrix([1,2,3],[4,5,6])
m3 = Matrix([1,2,3],[5,4,6])
> assert m1 == m2
E assert <exercises.matrix.Matrix object at 0x10ccd67d0> == <exercises.matrix.Matrix object at 0x10ccd6810>
我在这里缺少什么?我正在使用 Python 3.7.4 和 pytest 版本 5.1.2。提前感谢您的 cmets/answers
注意:我根据 ggorlen 的回答更改了实现,但我遇到了类似的问题
【问题讨论】:
错误在您的.row
方法中,您没有向我们展示。
我认为情况并非如此,该方法已经过测试并且工作正常,但也许我传递了错误的参数。会检查。谢谢
您是否无意中忽略了row()
方法?如果该方法存在,请显示minimal reproducible example。
@ggorlen 我在课堂上添加了一些细节。请检查编辑。感谢您的宝贵时间
看起来同样的问题——不存在名为 _rows()
的方法。要么使用带括号的私有数据类_rows[]
,要么使用带括号的函数.row()
。看我的回答。还有一个逻辑问题:如果other
矩阵的行数比self
多,您可能会得到误报,因为循环从不考虑多余的行。
【参考方案1】:
比较中的行应该是这样的:
for i, i_row in enumerate(self._rows):
if i_row != other._rows[i]:
return False
但是如果other
的行数比self
多,这仍然不会返回正确的结果,所以:
def __eq__(self, other):
return isinstance(self, other.__class__) and \
len(other._rows) == len(self._rows) and \
all([x == y for x, y in zip(self._rows, other._rows)])
该属性名为_rows
,我们需要使用[]
来索引列表,而不是括号。
一个可能更快的版本可以在比较失败的情况下提前退出:
def __eq__(self, other):
if isinstance(self, other.__class__) and \
len(other._rows) == len(self._rows):
for i, row in enumerate(self._rows):
if row != other._rows[i]:
return False
return True
return False
在您的测试中,您可能有错字:
m1 = Matrix([[1,2,3],[4,5,6]]) # <-- this matrix has an extra `[]` wrapper
m2 = Matrix([1,2,3],[4,5,6]) # <-- but this one just uses flat lists
所以这些矩阵将不相等。
小建议:
在参数错误时引发ValueError
或ArgumentError
而不是SystemError
。
考虑使用Numpy.matrix 而不是滚动您自己的矩阵。
【讨论】:
我会试试你的解决方案。关于 Numpy.matrix,事实上这是一个练习,我应该只使用标准库函数。感谢您的宝贵时间 我按照您的建议更改了__eq__
,但我遇到了同样的问题。检查版本
m1 = Matrix([[1,2,3],[4,5,6]])
(额外的[]
s)的错字修正了吗?
我相信这是列表列表的有效语法,但似乎不是。非常感谢,它现在可以工作了,你的解决方案比我的更干净优雅
zip_longest
方法效率较低,因为如果列表不相等,它会检查所有内容,直到遇到None == some_row_list
。因此,如果我们只是预先检查长度,如果长度不同,我们可以立即返回,并且可以使用常规的zip
,因为我们保证我们有相同的行数。它仍然不是最有效的解决方案,因为如果两个列表比较失败(使用常规循环而不是列表理解/any
),则不会提前中断,但它应该是正确的。以上是关于python __eq__ 测试失败的主要内容,如果未能解决你的问题,请参考以下文章