ZetCode

Python __reversed__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南将深入探讨 Python 的 __reversed__ 方法,这是实现序列反向迭代的特殊方法。我们将涵盖基本用法、自定义序列实现以及实际示例。

基本定义

__reversed__ 方法返回一个迭代器,该迭代器按反向顺序产生项。它由内置的 reversed() 函数调用。

主要特点:它应该返回一个迭代器对象,对于序列类型是可选的,并且对于某些类型提供比切片更有效的反向迭代。它支持自定义反向迭代行为。

基本的 __reversed__ 实现

这是一个简单的实现,展示了 __reversed__ 如何与自定义序列类一起工作。该方法返回一个反向迭代器。

basic_reversed.py
class MySequence:
    def __init__(self, data):
        self.data = data
    
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, index):
        return self.data[index]
    
    def __reversed__(self):
        return reversed(self.data)

seq = MySequence([1, 2, 3, 4, 5])
for item in reversed(seq):
    print(item)

此示例展示了一个实现 __reversed__ 的序列类,该类将工作委托给内置的 reversed() 函数。输出将打印从 5 到 1 的数字。

该类还实现了 __len____getitem__,使其成为一个真正的序列。__reversed__ 增强了其功能。

自定义反向迭代器

为了获得更多控制,您可以创建一个自定义反向迭代器类,而不是使用内置的 reversed()

custom_iterator.py
class ReverseIterator:
    def __init__(self, sequence):
        self.sequence = sequence
        self.index = len(sequence)
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index -= 1
        return self.sequence[self.index]

class MySequence:
    def __init__(self, data):
        self.data = data
    
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, index):
        return self.data[index]
    
    def __reversed__(self):
        return ReverseIterator(self)

seq = MySequence([10, 20, 30, 40])
for item in reversed(seq):
    print(item)

此实现展示了一个专门的 ReverseIterator 类,该类处理反向迭代逻辑。它维护一个递减的索引。

迭代器同时实现了 __iter____next__,使其成为一个真正的迭代器。这种方法提供了最大的灵活性。

反转链表

__reversed__ 对于数据结构特别有用,在这些数据结构中,反向迭代不像通过索引向后计数那样简单。

linked_list.py
class Node:
    def __init__(self, value, next_node=None):
        self.value = value
        self.next = next_node

class LinkedList:
    def __init__(self):
        self.head = None
    
    def append(self, value):
        if not self.head:
            self.head = Node(value)
        else:
            current = self.head
            while current.next:
                current = current.next
            current.next = Node(value)
    
    def __iter__(self):
        current = self.head
        while current:
            yield current.value
            current = current.next
    
    def __reversed__(self):
        values = list(self)
        return reversed(values)

lst = LinkedList()
lst.append(1)
lst.append(2)
lst.append(3)

for item in reversed(lst):
    print(item)

此链表实现展示了 __reversed__ 如何与非索引序列一起工作。它首先将列表转换为 Python 列表。

对于大型链表,更有效的方法是实现一个真正的反向迭代器,该迭代器在不创建临时列表的情况下遍历列表。

使用切片语法反转

对于支持切片操作的序列,__reversed__ 可以利用它来实现简洁的实现。

slice_reversed.py
class MyRange:
    def __init__(self, start, stop):
        self.start = start
        self.stop = stop
    
    def __len__(self):
        return max(0, self.stop - self.start)
    
    def __getitem__(self, index):
        if index < 0:
            index += len(self)
        if 0 <= index < len(self):
            return self.start + index
        raise IndexError("Index out of range")
    
    def __reversed__(self):
        return self[::-1]

r = MyRange(1, 6)
for num in reversed(r):
    print(num)

这个类似 range 的类使用 Python 的切片语法实现了 __reversed__[::-1] 切片创建序列的反向视图。

切片方法简洁,但对于非常大的序列可能不是最高效的,因为它会在内存中创建一个新的序列对象。

反转自定义集合

对于更复杂的集合,__reversed__ 可以实现自定义的反向迭代逻辑,而不依赖于索引。

custom_collection.py
class TreeNode:
    def __init__(self, value):
        self.value = value
        self.children = []
    
    def add_child(self, node):
        self.children.append(node)

class Tree:
    def __init__(self, root):
        self.root = root
    
    def __reversed__(self):
        def traverse(node):
            for child in reversed(node.children):
                yield from traverse(child)
            yield node.value
        return traverse(self.root)

root = TreeNode(1)
child1 = TreeNode(2)
child2 = TreeNode(3)
root.add_child(child1)
root.add_child(child2)
child1.add_child(TreeNode(4))
child1.add_child(TreeNode(5)))

tree = Tree(root)
for value in reversed(tree):
    print(value)

这个树结构使用 __reversed__ 实现反向深度优先遍历。它以反向顺序递归地产生子节点。

该实现使用嵌套的生成器函数来处理递归遍历。这种模式对于复杂的数据结构很常见。

最佳实践

资料来源

作者

我的名字是 Jan Bodnar,我是一名充满激情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有超过十年的经验。

列出所有 Python 教程