__next__和next参数

时间:2017-02-01 20:04:10

标签: python python-3.x iterator

我正在编写双链表的实现。为了遍历列表,我使用的是:

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_nextget_previous只是self.nextself.previous的获取者。

然而,PyCharm因为试图打电话给next而对我大喊大叫 next(some_node, direction=-1)。这样做的正确方法是什么?

3 个答案:

答案 0 :(得分:2)

__iter__外,还有__reversed__。两者都需要返回iterators__next__方法应该在iterators上实现(不在节点类上)。请注意,所有魔术方法(当由next等函数调用而不是直接调用时)需要实现预期参数而不是更多 - 而不是更少。

例如,双向链接列表可以实现__iter____reversed__,并依赖于节点的nextprevious属性:

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获得相同的效果)