Python:有__slots__时如何写__repr__

Python: How to write __repr__ when having __slots__

我想知道如何为 class 和 __slots__ 实现 __repr__ 方法。据我理解__repr__,应该是return一个字符串,可以用来构造我们称之为__repr__的对象。换句话说,给 repr(object) 一个 Python 解释器应该构造 object.

但是,如果有一个 class 有 __slots__,我很难想象如何实现它。这是因为当使用 __slots__ 时,插槽中的某些属性可能会被初始化并具有值,而其他属性可能不会。那么我如何找出哪些属性被初始化以及将它们传递给 __repr__ 字符串的值?

这种 class 的最小示例:

class TestClass:
    __slots__ = 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', '__dict__'

    def __init__(self, something, something_else, **kwargs):
        self.something = something
        self.something_else = something_else

        for key, value in kwargs.items():
            setattr(self, key, value)

    def __repr__(self):
        return '%s(%r, %r)' %(self.__class__.__name__, self.something, self.something_else)

有什么建议吗?

As far as I understand __repr__, it is supposed to return a string which can be used to construct the object of which we called __repr__. In other words, giving repr(object) to a Python interpreter should construct object.

这只是建议,不是强加:

If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form <...some useful description...> should be returned.

并且“如果可能的话”的解释非常松散和薄弱,许多对象根本不会打扰,例如class 或函数 的 repr 可以 产生其源表示,但不要这样做,因为它的用例很少,而且它比有用更烦人。

However, if there is a class having __slots__, I find it hard to imagine how to implement this. This is because when using __slots__, some of the attributes in slots may be initialised and have values, others probably won't.

当然不是。我从来没有写过一个 class 的插槽,其中并非所有插槽都一直被填充。再加上 hasattr/getattr 可以很好地处理插槽。

尽管我不得不问:你是cargo-culting __slots__吗?是否有人曾经告诉您使用插槽,现在您到处都在使用它们?

slots 是一个内存优化工具,重点是例如每个成员只需要一个指针(+一些对象开销)而不是 dict 实例的开销(和它的摊销重新分配)。当您通常不填充插槽时使用插槽几乎没有意义,更不用说将 __dict__ 添加到您的插槽。

更不用说最近的 Python 3 次迭代已经对 instance-dicts 添加了各种优化,使得插槽的用处更少,至少随着属性数量的增加(在相当大的 classes从 3.6 开始,我们发现差异小于 5%,尽管在小 classes 上它可能仍然很重要)。