[英]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.