【问题标题】:Correct way to write __repr__ function with inheritance使用继承编写 __repr__ 函数的正确方法
【发布时间】:2017-11-04 15:23:41
【问题描述】:

我正在尝试使用 OOP python,但我不确定 __repr__ 函数继承。由于父类函数看起来像这样:

def __repr__(self):
    '''Returns representation of the object'''
    return("{}({!r})".format("Class name", self._param))

我想知道使用以下通用方法(也可能适用于儿童课程)是否更好:

def __repr__(self):
    '''Returns representation of the object'''
    return("{}({!r})".format(self.__class__.__name__, self._param))

或者如果在每个类中重写该函数是一个好习惯。

另外,请忽略编码部分,因为我把它留在后面了。

【问题讨论】:

  • 一般来说,如果你不想扩展方法,重写它就可以了。
  • 如果所有子类都有_param属性,那么他们从父类继承__repr__是相当安全的。

标签: python oop inheritance repr


【解决方案1】:

__repr__ 在 Python 的数据模型中有特殊的含义:

object.__repr__(self)

repr() 内置函数调用以计算对象的“官方”字符串表示。 如果可能的话,这应该看起来像一个有效的 Python 表达式,可用于重新创建具有相同值的对象(给定适当的环境)。如果这不可能,则应返回<...some useful description...> 形式的字符串。返回值必须是字符串对象。如果一个类定义了__repr__(),但没有定义__str__(),那么当需要该类实例的“非正式”字符串表示时,也会使用__repr__()

这通常用于调试,因此表示信息丰富且明确是很重要的。

这意味着__repr__ 返回的字符串应该可以用来创建另一个类似的对象。所以__repr__经常需要覆盖的东西,不是因为__class__.__name__,而是因为必须在表示中捕获“状态”。

class A(object):
    def __init__(self, param):
        self._param = param

    def __repr__(self):
        '''Returns representation of the object'''
        return("{}({!r})".format(self.__class__.__name__, self._param))

那么当你为__init__添加参数时,你绝对应该覆盖__repr__

class B(A):
    def __init__(self, param1, param2):
        self._param = param1
        self._param2 = param2

    def __repr__(self):
        '''Returns representation of the object'''
        return("{}({!r})".format(self.__class__.__name__, self._param, self._param2))

但如果超类的__repr__ 仍然准确“描述”子类,那么重载__repr__ 没有意义:

class B(A):
     pass

但是,使用 self.__class__.__name__ 而非硬编码类名始终是一个不错的选择,以防万一您或其他人将其子类化。

【讨论】:

  • 你应该从它的repr推荐中重新创建一个对象的能力与一粒盐:它对于某些类型的对象来说很棒,但它仍然是在Pyhton的input会调用的时候想到的用户输入的值上的“eval”:这是交互式使用 Python 语言的另一种心态。根据对象的类型,它并不实用——有时甚至不合需要——taht repr 以这种方式工作。
  • @jsbueno 这对于调试(以及当您在 StackOverflow 上发帖时)更重要。当表示包含定义实例的所有必要信息时,重新创建特定状态或“查看”正在发生的事情会容易得多。
【解决方案2】:

是的 - - 这不仅仅是“ok”,而是在几乎每个项目和类层次结构中更实用。

实际上,这几乎是什么时候使用类继承的完美“教科书示例”,只是让超类中的代码被重用。

【讨论】:

    猜你喜欢
    • 2012-04-11
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多