猴子修补重写方法

2024-09-30 20:23:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我想弄清楚为什么下面的例子行不通。在

class BaseClass(object):
    def __init__(self):
        self.count = 1

    def __iter__(self):
        return self

    def next(self):
        if self.count:
            self.count -= 1
            return self
        else:
            raise StopIteration


class DerivedNO(BaseClass):
    pass


class DerivedO(BaseClass):
    def __init__(self):
        self.new_count = 2
        self.next = self.new_next

    def new_next(self):
        if self.new_count:
            self.new_count -= 1
            return None
        else:
            raise StopIteration


x = DerivedNO()
y = DerivedO()

print x
print list(x)
print y
print list(y)

输出如下:

^{pr2}$

如您所见,当我试图在__init__中分配next()方法时,DerivedO中的新方法将不会被重写。为什么?对next的一个简单调用可以正常工作,但在使用迭代技术时根本不起作用。在

编辑:我知道我的问题不是很清楚。AttributeError不是我要解决的问题。但它确实表明next()是在BaseClass上调用的,而不是像我想的那样在DerivedO上调用。在


Tags: selfnewreturnifinitdefcountelse
2条回答

由于DerivedO从不初始化count属性,因此在执行next方法时会发生AttributeError。在

您可以通过安排调用BaseClass.__init__(显式调用或使用super)来避免此错误:

class DerivedO(BaseClass):
    def __init__(self):
        super(DerivedO, self).__init__()
        self.new_count = 2

    def next(self):
        if self.new_count:
            self.new_count -= 1
            return None
        else:
            raise StopIteration

另外,您可以简单地重写(重定义)next,而不是定义new_next。在

不能在实例上使用monkeypatch __iter__(self)或扩展为next(self),因为这些方法被视为类方法,而不是CPython内部优化(请参见Special method lookup for new-style classes以了解其原因)。在

如果需要monkeypatch这些方法,则需要直接在类上设置它们:

class DerivedO(BaseClass):
    def __init__(self):
        self.new_count = 2
        self.__class__.next = self.__class__.new_next

    def new_next(self):
        if self.new_count:
            self.new_count -= 1
            return None
        else:
            raise StopIteration

上面的方法可以工作;请注意,我将__class__.next设置为unbound函数new_next,而不是绑定方法。在

相关问题 更多 >