python2和python3中dict的__repr__()
Posted
技术标签:
【中文标题】python2和python3中dict的__repr__()【英文标题】:dict's __repr__() in python2 and python3 【发布时间】:2013-11-02 11:25:37 【问题描述】:我在一个代码库(2.6、2.7 和 3.3+)中仅将 python 库从 python 2 移植到 python 2 和 3。剩下的主要问题是很多测试都使用这样的东西:
def test(self):
example = u'foo': u'bar'
self.assertEqual(str(example), "u'foo': u'bar'")
在 python 2 中有效,但在 python3 中引发异常:
AssertionError: "'foo': 'bar'" != "u'foo': u'bar'"
除了“测试不同”之外,还有处理这些问题的标准方法吗?重载__repr__
?
【问题讨论】:
为什么要进行这些测试?他们试图验证什么?这闻起来很强烈XY problem。 澄清一下:在实际代码中,example是dict的子类,是另一个函数的返回值。这个子类有它自己的__repr__
,包装了dict的__repr__
,但是'u's还在里面
这并没有说明任何事情。你到底想在这里测试什么?问题是子类的__eq__
不能与基本dict
对象一起工作,所以您试图通过比较它们的repr
来解决它?还是……?
@ChristianGeier:您正在与固定字符串进行比较;如果您有测试自定义__repr__
,则生成带有或不带有u
前缀的固定字符串。
@abarnert __eq__
确实有效,我不知道为什么原作者通过__repr__
进行测试。我想我会使用它并完成它。
【参考方案1】:
摆脱那些测试;它们几乎没用:
这将测试dict.__repr__
的 Python 实现是否正常工作。 Python 本身已经对此进行了测试;而是专注于项目代码库。如果 Python 无法正确呈现字典表示,则修复该问题不是您项目的工作。
Python 字典没有固定的顺序;测试它们的表示是否与给定的字符串匹配是不稳定的。
此外,Python 3.3 引入了哈希随机化,这意味着给定字典的顺序将在每次调用中发生变化。见PYTHONHASHSEED
。
如果您正在测试项目 API 调用的结果,请改用 self.assertEqual()
测试字典是否相等;如果两个字典不匹配,它将使用assertDictEqual()
为您提供有意义的错误消息。
由于 Python 3.3 将 u'foo'
解释为类型 str
的文字,因此将输出与 u'foo': u'bar
进行比较将适用于 Python 2.6、2.7 和 3.3 及更高版本。
【讨论】:
另外,在 python3 中,字符串默认变成了 unicode。这意味着标准字符串不再有u
前缀。
检查self.assertEqual(example, ast.literal_eval(u'foo': u'bar'))
不太可能,并且服务于类似目的......但我仍然无法想象那个目的可能是什么,所以很难说它是否相似够了。
@MartijnPieters,公平地说,在 this 示例中排序无关紧要:len(example) == 1
。
assertDictEqual
在 2.6 中不存在。而在 2.7 和 3.3 中,虽然它确实存在,但“此方法将默认用于比较对 assertEqual()
的调用中的字典”,因此不会增加太多。
@TimPeters:当然;但 OP 没有测试长度;他正在测试 Python dict.__repr__()
是否仍在工作..【参考方案2】:
我怀疑这不是您的真实代码,而您的真实代码正在做一些不那么愚蠢的事情:尝试验证字典是否与某些预期结果匹配。
这样做的方法是直接比较字典,而不是比较它们的字符串表示:
self.assertEqual(example, u'foo': u'bar')
这适用于 2.x 和 3.x(因为您需要 3.3+,这意味着 u
前缀是合法的,如果不需要的话)。
【讨论】:
以上是关于python2和python3中dict的__repr__()的主要内容,如果未能解决你的问题,请参考以下文章