2

我将实现一些容器对象。

class A:
    def __init__(self, L):
        self.L = list(L)
    def __len__(self):
        return len(self.L)

class B:
    def __init__(self, L):
        self.L = list(L)
        self.__len__ = self.L.__len__

在第一种情况下,同时len()工作.__len__()

>>> a = A(range(10))
>>> a.__len__()
10
>>> len(a)
10

但在第二种情况下,我得到错误len()

>>> b = B(range(10))
>>> b.__len__()
10
>>> len(b)
Traceback (most recent call last):
  File "<pyshell#93>", line 1, in <module>
    len(b)
TypeError: object of type 'B' has no len()
  1. 为什么len()在第二种情况下不起作用,而.__len__()被定义并正常工作?
  2. 通常可以将一些方法从一个对象分配给另一个对象吗?就像我对self.L.__len__().
4

2 回答 2

3

你不能这样做,特殊的钩子方法__len__总是类型上查找,而不是在实例上。

换句话说,len(ob)调用type(ob).__len__(ob)而不是 ob.__len__()

请参阅特殊方法查找文档;我解释了为什么这是在以前的答案中。

对于不是特殊钩子的方法(以双下划线开头和结尾),您可以自由地将方法分配给您的实例,没有技术原因阻止您这样做。

如果您的目标是提供外观对象,那么一定要复制方法。我认为这样做没有明显的缺点。直接在您的实例上调用该方法,而不必通过包装器方法进行路由,性能会稍好一些(您为包装器方法保存堆栈推送和弹出)。

于 2013-03-01T14:18:53.160 回答
2

精美的 Python 文档告诉我们,

对于新式类,特殊方法的隐式调用只有在对象类型上定义时才能保证正常工作,而不是在对象的实例字典中。

于 2013-03-01T14:19:21.717 回答