在print函数中使用类名

2024-04-16 19:15:52 发布

您现在位置:Python中文网/ 问答频道 /正文

新来的Python。你知道吗

我有点问题。我想打印一个特定的输出,需要像点(x=1,y=2,z=3)(xyz的值当然可以不同)。你知道吗

代码如下:

class Point:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

    def __str__(self):
        return f"Point(x={self.x}, y={self.y}, z={self.z})"

这是测试代码:

import unittest

from point import Point


class PointTests(unittest.TestCase):

    """Tests for Point."""

    def test_attributes(self):
        point = Point(1, 2, 3)
        self.assertEqual((point.x, point.y, point.z), (1, 2, 3))
        point.x = 4
        self.assertEqual(point.x, 4)

    def test_string_representation(self):
        point = Point(1, 2, 3)
        self.assertEqual(str(point), 'Point(x=1, y=2, z=3)')
        self.assertEqual(repr(point), 'Point(x=1, y=2, z=3)')
        point.y = 4
        self.assertEqual(str(point), 'Point(x=1, y=4, z=3)')
        self.assertEqual(repr(point), 'Point(x=1, y=4, z=3)')

    def test_equality_and_inequality(self):
        p1 = Point(1, 2, 3)
        p2 = Point(1, 2, 4)
        p3 = Point(1, 2, 3)
        self.assertNotEqual(Point(1, 2, 3), Point(1, 2, 4))
        self.assertEqual(Point(1, 2, 3), Point(1, 2, 3))
        self.assertFalse(Point(1, 2, 3) != Point(1, 2, 3))
        self.assertNotEqual(p1, p2)
        self.assertEqual(p1, p3)
        p3.x, p3.z = p3.z, p3.x
        self.assertNotEqual(p1, p3)
        self.assertTrue(p1 != p3)
        self.assertFalse(p1 == p3)

我遇到的问题是,当我在打印格式中使用“”时,在str函数中出现断言错误:

AssertionError: 'point.Point object at 0x7fbd8850b190' != 'Point(x=1, y=2, z=3)'

但当我用其他东西的时候,它就会被打印出来。例如,假设我使用而不是

'points(x=1, y=2, z=3)' != 'Point(x=1, y=2, z=3)'

为什么会发生这种情况,我该怎么处理?你知道吗


Tags: testimportselfdefunittestclasspointp2
2条回答

关于python3,您有两个失败的测试。你知道吗

======================================================================
FAIL: test_equality_and_inequality (test_point.PointTests)
                                   
Traceback (most recent call last):
  File "/home/josef/tmp/deleteme/test_point.py", line 29, in test_equality_and_inequality
    self.assertEqual(Point(1, 2, 3), Point(1, 2, 3))
AssertionError: <point.Point object at 0x7f7a20cff050> != <point.Point object at 0x7f7a20cff090>

发生这种情况是因为声明新对象的返回是具有唯一id的对象本身。计算Point(1, 2, 3)会返回一个唯一的东西,如<point.Point object at 0x7f7a20cff050>,而不是类本身。因此,如果实例化一个类的两个实例,它们必然是不同的。你知道吗

======================================================================
FAIL: test_string_representation (test_point.PointTests)
                                   
Traceback (most recent call last):
  File "/home/josef/tmp/deleteme/test_point.py", line 19, in test_string_representation
    self.assertEqual(repr(point), 'Point(x=1, y=2, z=3)')
AssertionError: '<point.Point object at 0x7f7a20d75f90>' != 'Point(x=1, y=2, z=3)'
- <point.Point object at 0x7f7a20d75f90>
+ Point(x=1, y=2, z=3)

Python类可以有__str__方法和__repr__方法。前者主要用于返回对象的字符串表示形式,因此如果您将其显示给人类,则会得到一些看起来不错的东西。我认为后者使用较少(我仍然通常定义它),但据我所知,它应该启用“对象到表示到对象”的往返;以这样一种方式显示实例:理论上,您可以eval()该字符串表示并忠实地再现对象。你知道吗

您的类定义没有__repr__,因此测试当然会失败。有时(对于较大的值有时)如果我懒惰,我会这样做:

def __str__(self):
    return self.__repr__()

错误发生在

self.assertEqual(repr(point), 'Point(x=1, y=2, z=3)')

由于您习惯性地只在__Point__上定义了__str__方法,因此__repr__仍然是内置方法,导致类似"point.Point object at 0x7fbd8850b190"的结果。要解决这个问题,请定义Point__repr__。你知道吗

当您定义__repr__方法时,python使用它作为__str__的默认方法,但它不会反过来做。你知道吗

对于您的(不是很小的)代码示例,这仍然会导致错误

self.assertEqual(Point(1, 2, 3), Point(1, 2, 3))

这是因为这条线不是测试表示的相等性,而是测试对象的相等性。由于实例化Point两次,因此assertEqual的第一个参数实际上与第二个参数不同,即使它们都是Point的实例,而且它们的实例变量相等。你知道吗

您可以将这些对象理解为类似“双胞胎”或“克隆体”的东西:即使它们的所有属性都相同,它们仍然具有不同的“身份”。你知道吗

如果我们想把“twins”看作“equal”,Python允许我们定义一个由Python用来检查对象相等性的相等关系。我们可以通过实现__eq__方法来定义这一点。很可能你想要的是:

class Point:
    def  __init__(x, y, z):
        self.x = x
        self.y = y
        self.z = z

    def __repr__(self):
        return f"Point(x={self.x}, y={self.y}, z={self.z})"

    def __eq__(self, other):
        return self.__repr__() == other.__repr__()

阅读Python的“魔术方法”的介绍,例如https://rszalski.github.io/magicmethods/,可能是个好主意

相关问题 更多 >