编写repr方法

Posted

技术标签:

【中文标题】编写repr方法【英文标题】:Writing a repr method 【发布时间】:2016-10-13 05:50:43 【问题描述】:

情况: 我是 python 新手,目前正在尝试学习技巧,我尝试创建一个链表类来帮助更好地理解语言及其结构。我知道__repr__ 函数基本上应该返回与__str__ 相同的东西,但我不确定实际的区别是什么。

到目前为止,这是我的课程:

class LinkedList:
    class Node:
        def __init__(self, val, prior=None, next=None):
            self.val = val
            self.prior = prior
            self.next  = next

    def __init__(self):
        self.head = LinkedList.Node(None) 
        self.head.prior = self.head.next = self.head 
        self.length = 0

    def __str__(self):
        """Implements `str(self)`. Returns '[]' if the list is empty, else
        returns `str(x)` for all values `x` in this list, separated by commas
        and enclosed by square brackets. E.g., for a list containing values
        1, 2 and 3, returns '[1, 2, 3]'."""
        if len(self)==0:
            return '[]'
        else:
            return '[' +  ', '.join(str(x) for x in self) + ']'

    def __repr__(self):
        """Supports REPL inspection. (Same behavior as `str`.)"""
        return '[' +  ', '.join(str(x) for x in self) + ']'

当我根据下面的代码测试此代码时,我会收到一个错误,基本上是说使用 repr 函数时实际上没有返回空白字符串 '[]'。我如何编辑这个方法体来解决这个问题?我也尝试过return str(self),但我不确定为什么它也不起作用。

from unittest import TestCase
tc = TestCase()

lst = LinkedList()
tc.assertEqual('[]', str(lst))
tc.assertEqual('[]', repr(lst))

lst.append(1)
tc.assertEqual('[1]', str(lst))
tc.assertEqual('[1]', repr(lst))

【问题讨论】:

“我知道__repr__ 函数基本上应该返回与__str__ 相同的东西” - 我不知道你是怎么知道的,但那是不对,请参阅 __str____repr__ 上的文档。 您显示的代码无法按照编写的方式运行(至少您已经省略了__len____iter__ 方法),这使得故障排除变得非常困难。虽然我们很欣赏一个简洁的问题,但我们需要一个真正有效的minimal reproducible example! 这有所有的答案:Difference between str and repr? 【参考方案1】:

__repr__ 函数返回 Python 对象的字符串表示形式,Python 解释器可以评估该字符串表示形式以实例化该对象的另一个实例。所以如果你有一个列表:

x = ['foo', 'bar']

它的__repr__ 字符串是:

x_str = repr(x)
print(x_str)
>>>>
"['foo', 'bar']"

你可以这样做:

x2 = eval(x_str)
print(type(x2))
>>>>
<class 'list'>

这是一种获取 Python 对象的字符串表示形式的方法,该对象可以转换回所述对象的新实例。

__str____repr__ 之间的区别基本上是前者返回的对象的字符串表示意在被人读取,而后者返回的对象的字符串表示意在被 Python 解释器解析.对此要非常小心!

在您的示例代码中,__str____repr__ 似乎返回相同的字符串表示形式。没关系。但是,如果您愿意,您可以让您的 __str__ 返回一些更漂亮的格式版本(例如带有回车符且没有括号),但 __repr__ 应该始终返回一个可由 Python 解释器解析以重构对象的字符串.

【讨论】:

这是思考 repr 的好方法!我想知道我应该如何构建我的输出,这很好地回答了它。但是,应该注意 repr 和 eval 不应该用作序列化程序,因为在某些情况下它会被破坏。但这是创建代表的一个很好的标准。

以上是关于编写repr方法的主要内容,如果未能解决你的问题,请参考以下文章

对象名称重载__str__ 和__repr__

__ repr__方法和列表上的repr()返回不同的对象

几个类的内置方法

SQLAlchemy 为大型表定义 __repr__ 的最佳方法

Python详解类的 __repr__() 方法

repr方法字符串输出实例对象的值