我将实现一些容器对象。
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()
len()
不起作用,而.__len__()
已定义且正常工作?self.L.__len__()
所做的那样。答案 0 :(得分:3)
你不能这样做,像__len__
这样的特殊钩子方法总是在类型上查找,而不是在实例上查找。
换句话说,len(ob)
调用type(ob).__len__(ob)
,不是 ob.__len__()
。
见Special method lookup documentation;我解释了为什么这是in a previous answer。
对于不特殊挂钩(以双下划线开头和结尾)的方法,您可以自由地为您的实例分配方法,没有技术原因阻止您这样做。
如果您的目标是通过各种方式提供facade object,请复制方法。我认为没有明显的缺点。直接在您的实例上调用方法而不必通过包装器方法进行路由会稍微好一些(为包装器方法保存堆栈推送和弹出)。
答案 1 :(得分:2)
The fine Python documentation告诉我们
对于新式类,只保证在对象的类型上定义特殊方法的隐式调用才能正常工作,而不是在对象的实例字典中。