我正在编写一个简单的链表实现,如下所示:
class Node(object):
def __init__(self, value):
self.value = value
self._next = None
def __iter__(self):
here = self
while here:
yield here
here = here._next
def __len__(self):
print("Calling __len__ on: {}".format(self))
return sum(1 for _ in self)
def append_to_tail(self, value):
if self._next is None:
self._next = Node(value)
else:
self._next.append_to_tail(value)
def print_list(ll):
print(ll.value)
if ll._next:
print_list(ll._next)
my_list = Node('a')
my_list.append_to_tail('b')
my_list.append_to_tail('c')
print_list(my_list)
此代码在没有__len__
方法的情况下运行良好。删除这三行并运行上面的代码输出:
first
second
third
但是,如果存在__len__
方法,则结果为:
first
Calling __len__ on: <__main__.Node object at 0x108804dd0>
Calling __len__ on: <__main__.Node object at 0x108804dd0>
<snip>
Calling __len__ on: <__main__.Node object at 0x108804dd0>
Calling __len__ on: <__main__.Node object at 0x108804dd0>
Traceback (most recent call last):
File "len_example.py", line 31, in <module>
print_list(my_list)
File "len_example.py", line 24, in print_list
if ll._next:
File "len_example.py", line 14, in __len__
return sum(1 for _ in self)
File "len_example.py", line 14, in <genexpr>
return sum(1 for _ in self)
File "len_example.py", line 8, in __iter__
while here:
File "len_example.py", line 14, in __len__
return sum(1 for _ in self)
File "len_example.py", line 14, in <genexpr>
return sum(1 for _ in self)
<snip>
File "len_example.py", line 8, in __iter__
while here:
File "len_example.py", line 13, in __len__
print("Calling __len__ on: {}".format(self))
RuntimeError: maximum recursion depth exceeded while calling a Python object
请注意输出中是否存在first
。 print_list()
执行一次,但在递归之前隐式调用__len__()
方法。什么叫这种方法?
我在python 3.3.1和2.7.3
中看到了相同的行为答案 0 :(得分:11)
您在布尔上下文中使用here
:
while here:
这将使用__len__
查看它是否为空容器(例如是假y),请参阅Truth Value Testing:
可以测试任何对象的真值,以便在
if
或while
条件下使用,或者作为下面布尔运算的操作数。以下值被视为false:[...]
- 用户定义的类的实例,如果类定义了
__nonzero__()
或__len__()
方法,则该方法返回整数零或bool值False
。
对于您的用例,请改用is not None
:
while here is not None: