我想弄清楚为什么以下示例不起作用。
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)
这是输出:
<__main__.DerivedNO object at 0x7fb2af7d1c90>
[<__main__.DerivedNO object at 0x7fb2af7d1c90>]
<__main__.DerivedO object at 0x7fb2af7d1d10>
Traceback (most recent call last):
File "playground.py", line 41, in <module>
print list(y)
File "playground.py", line 11, in next
if self.count:
AttributeError: 'DerivedO' object has no attribute 'count'
正如您所见,当我尝试在DerivedO
中分配next()
方法时,__init__
中不会覆盖新方法。这是为什么?对next的简单调用可以正常工作,但在使用迭代技术时根本不会。
编辑:我意识到我的问题并不完全清楚。 AttributeError不是我想要解决的问题。但它确实显示next()
会在BaseClass
而不是DerivedO
上调用,因为我认为会这样。
答案 0 :(得分:5)
您不能对实例进行__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
设置为未绑定函数new_next
,而不是绑定方法。
答案 1 :(得分:-1)
由于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
此外,您可以简单地覆盖(重新定义)new_next
,而不是定义next
。