如何在继承时在init中设置绑定的双下(dunder)方法?

时间:2014-11-29 00:40:05

标签: python class inheritance override

假设我定义了一个自定义列表类型:

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__

0 个答案:

没有答案