假设我定义了一个自定义列表类型:
class MyList(list):
def __reversed__(self):
print 'called MyList.__reversed__'
return super(MyList, self).__reversed__()
def count(self, item):
print 'called MyList.count'
return super(MyList, self).count(item)
所有这一切都表明在调用__reversed__
或count
时。
现在假设我使用MyList
成员变量定义另一个类型。我想在我的新类型上使用几种方法来调度MyList
方法,因此我在__init__
中设置方法,如下所示:
class GoodList:
def __init__(self, iterable):
self._list = MyList(iterable)
self.__reversed__ = self._list.__reversed__
self.count = self._list.count
def __getitem__(self, index):
return 0
def __len__(self):
return 0
稍后我决定GoodList
应该从collections.Sequence
继承。但是当我这样做时,行为会发生变化。作为一个例子,我定义BadList
,唯一的区别是继承:
from collections import Sequence
class BadList(Sequence):
def __init__(self, iterable):
self._list = MyList(iterable)
self.__reversed__ = self._list.__reversed__
self.count = self._list.count
def __getitem__(self, index):
return 0
def __len__(self):
return 0
现在,当我创建GoodList
并致电__reversed__
和count
时,我会收到我期望的消息,从MyList
打印出来。这是执行它的代码:
print 'GOOD ' + '*' * 75
good = GoodList([1, 2, 3, 4, 5])
print 'GOOD list(reversed(good))'
print list(reversed(good))
print 'GOOD good.count(3)'
print good.count(3)
这是输出:
GOOD ***************************************************************************
GOOD list(reversed(good))
called MyList.__reversed__
[5, 4, 3, 2, 1]
GOOD good.count(3)
called MyList.count
1
相反,当我创建BadList
并致电__reversed__
和count
时,我会收到我期望仅count
的消息。将__reversed__
方法分派给继承的Sequence.__reversed__
方法。这是执行它的代码:
print 'BAD ' + '*' * 76
bad = BadList([1, 2, 3, 4, 5])
print 'BAD list(reversed(bad))'
print list(reversed(bad))
print 'BAD bad.count(3)'
print bad.count(3)
这是输出:
BAD ****************************************************************************
BAD list(reversed(bad))
[]
BAD bad.count(3)
called MyList.count
1
为什么方法调度在双下(dunder)方法中的工作方式不同?如何从Sequence
继承但仍然__reversed__
发送给_list.__reversed__
?