我正在使用python 3.7,我有这样的事情:
class Foo:
def __iter__(self):
yield from self.some_sequence
def __len__(self):
return len(list(self))
>>> len(Foo())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __len__
File "<stdin>", line 5, in __len__
File "<stdin>", line 5, in __len__
[Previous line repeated 496 more times]
RecursionError: maximum recursion depth exceeded
我敢肯定我缺少一些显而易见的原因,为什么这总是会导致递归错误,但是我不知道为什么。
答案 0 :(得分:8)
要计算对象的len
,请在对象上调用list
。
要弄清楚要保留多少空间,请list
调用对象上的len
。 (It uses PyObject_LengthHint
,它试图len
和__length_hint__
。)
要计算对象的len
...
存在无限递归。
(这即使是可行的,也__len__
的实现效率很低-通常__len__
应该是恒定时间的。)
答案 1 :(得分:5)
对象的len
方法调用对象的__len__
方法以计算长度。在您的情况下,在__len__
方法中,您再次调用len
中的list of self
,list
实际上最终调用了__len__
,这导致了递归。 / p>
下面的代码将导致递归:
def __len__(self):
return len(list(self))
您的通话是堆叠的,如下所示:
len(Foo()) --> __len__(self) --> len(list(self)) -->list(self)--> __len__(self)--> len(list(self)) --> list(self) --> __len__(self)-->so on
我不清楚您为什么要致电len(list(self))
。实际上,您应该获取存储在此类对象中的数据的长度并返回它,而不是调用len(list(self))
在list
功能实际上调用这实际上导致递归对象的__len__
功能。请参阅有关SO的相关问题:Why does list ask about __len__?
答案 2 :(得分:-1)
即使您没有像下面那样使用list
,也会出现相同的错误
def __len__(self):
return len((self))
实际上,您确实在没有终端条件的情况下进行了递归。目前尚不清楚您要在这里完成什么。