我正在编写双链表的实现。为了遍历列表,我使用的是:
class Node:
""" A node in our linked list """
def __init__(self, value: Any, next: Union['Node', None] =None,
previous: Union['Node', None] =None) -> None:
self.value = value
self.next = next
self.previous = previous
...
def __next__(self, direction: int =1) -> Union['Node', None]:
if direction == 1:
return self.get_next()
else:
return self.get_previous()
...
其中get_next
和get_previous
只是self.next
和self.previous
的获取者。
然而,PyCharm因为试图打电话给next
而对我大喊大叫
next(some_node, direction=-1)
。这样做的正确方法是什么?
答案 0 :(得分:2)
除__iter__
外,还有__reversed__
。两者都需要返回iterators
。 __next__
方法应该在iterators
上实现(不在节点类上)。请注意,所有魔术方法(当由next
等函数调用而不是直接调用时)需要实现预期参数而不是更多 - 而不是更少。
例如,双向链接列表可以实现__iter__
和__reversed__
,并依赖于节点的next
和previous
属性:
class Node(object):
def __init__(self, val, nxt, prv):
self.val = val
self.nxt = nxt
self.prv = prv
class DoublyLinkedList(object):
def __init__(self, base=None, last=None):
self.base = base
self.last = last
def prepend(self, val):
new = Node(val, self.base, None)
if self.base is None:
self.base = new
self.last = new
else:
self.base.prv = new
self.base = new
def append(self, val):
new = Node(val, None, self.last)
if self.last is None:
self.base = new
self.last = new
else:
self.last.nxt = new
self.last = new
def __iter__(self):
current = self.base
while current is not None:
yield current
current = current.nxt
def __reversed__(self):
current = self.last
while current is not None:
yield current
current = current.prv
例如:
dl = DoublyLinkedList()
dl.prepend(10)
dl.prepend(20)
dl.prepend(30)
for i in dl:
print(i.val)
给出:
30
20
10
与reversed
相似:
for i in reversed(dl):
print(i.val)
# prints:
10
20
30
答案 1 :(得分:1)
next
的额外参数是默认值,而__next__
没有任何额外的参数。 Python没有任何类型的双向迭代器。如果您的界面与for i in obj:
不完全相同,那么您应该自己编写。
答案 2 :(得分:1)
__next__
是iterator protocol的一部分,应按照所述协议中的描述使用,否则只会对其余的python产生问题。
在您的情况下,只需将函数重命名为简单next
并使用some_node.next(-1)
,但我会将direction
参数更改为布尔值,因为这是您使用它的方式,并且它的名字也是。像这样的例子
class None:
...
def next(self, forward:bool=True) -> Union['Node', None]:
if forward:
return self.get_next()
else:
return self.get_previous()
并使用some_node.next()
,some_node.next(False)
甚至some_node.next(0)
(使用0而不是False获得相同的效果)