簡體   English   中英

在打印功能中使用類名

[英]Using class name in print function

新手 Pythonista 在這里。

我有點問題。 我想打印一個特定的輸出,它需要像Point(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函數中,當我在打印格式中使用“ Point ”時,我拋出了一個斷言錯誤:

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

但是當我使用其他任何東西時,它會被打印出來。 例如,假設我使用points而不是Point

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

為什么會發生這種情況,我該如何解決這個問題?

錯誤發生在

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

由於您在__str__上僅自定義了__str__方法, __Point__ __repr__仍然是內置方法,導致類似於"point.Point object at 0x7fbd8850b190" 要解決此問題,請定義Point__repr__

當你定義__repr__方法時,python 使用它作為__str__的默認值,但它不會__str__做。

使用您的(不是最小的)代碼示例,這仍然會導致錯誤

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

這是因為這一行不測試表示的相等性,而是測試對象的相等性。 由於您實例化Point兩次,您的assertEqual的第一個參數實際上與第二個參數不同,即使它們都是Point實例,即使它們的實例變量相等。

您可以將這些對象理解為“雙胞胎”或“克隆體”:即使它們的所有屬性都相同,它們仍然具有不同的“身份”。

如果我們想將“孿生”視為“相等”,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/

在我使用 python 3 時,你有兩個失敗的測試。

======================================================================
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__()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM