ZetCode

Python reversed 函数

上次修改时间:2025 年 4 月 11 日

这篇综合指南探讨了 Python 的 reversed 函数,该函数返回序列的反向迭代器。我们将介绍内置序列、自定义对象以及反向迭代的实际示例。

基本定义

reversed 函数返回一个反向迭代器对象,该对象以相反的顺序访问元素。 它适用于任何实现 __reversed__ 或支持序列协议 (__len____getitem__) 的对象。

主要特点:返回一个迭代器(不是一个列表),保留原始序列,适用于字符串、列表、元组和自定义序列。 它具有内存效率,因为它不会创建新序列。

基本序列用法

这是一个简单的用法,使用不同的序列类型,展示了 reversed 如何处理列表、元组和字符串。

basic_reversed.py
# With lists
numbers = [1, 2, 3, 4, 5]
print(list(reversed(numbers)))  # [5, 4, 3, 2, 1]

# With tuples
colors = ('red', 'green', 'blue')
print(tuple(reversed(colors))) # ('blue', 'green', 'red')

# With strings
text = "hello"
print(''.join(reversed(text))) # "olleh"

此示例显示了 reversed 与不同序列类型的使用。 请注意,我们将迭代器转换为具体的类型(列表、元组、字符串)以进行显示。 原始序列保持不变。

对于字符串,我们使用 join 将反转后的字符重新组合成一个字符串。 reversed 函数适用于任何支持索引的序列。

具有 __reversed__ 的自定义对象

您可以通过实现 __reversed__ 特殊方法使自定义对象与 reversed 一起使用。 此示例创建了一个 CountDown 类。

custom_reversed.py
class CountDown:
    def __init__(self, start):
        self.start = start
    
    def __reversed__(self):
        n = 1
        while n <= self.start:
            yield n
            n += 1
    
    def __iter__(self):
        n = self.start
        while n > 0:
            yield n
            n -= 1

print("Normal iteration:")
for x in CountDown(5):
    print(x)  # 5, 4, 3, 2, 1

print("Reversed iteration:")
for x in reversed(CountDown(5)):
    print(x)  # 1, 2, 3, 4, 5

CountDown 类实现了 __iter____reversed__。 正常迭代递减计数,而反向迭代递增计数。

这演示了如何自定义对象的反向迭代行为。 __reversed__ 方法应返回一个迭代器。

Range 对象

reversed 函数可以高效地与 range 对象一起使用,创建一个反向迭代器,而无需在内存中生成所有数字。

range_reversed.py
# Forward range
for i in range(5):
    print(i)  # 0, 1, 2, 3, 4

# Reversed range
for i in reversed(range(5)):
    print(i)  # 4, 3, 2, 1, 0

# Large range (memory efficient)
large_range = reversed(range(1, 1000001))
print(next(large_range))  # 1000000
print(next(large_range))  # 999999

此示例显示了 reversed 如何与 range 对象一起使用。 反向迭代具有内存效率,尤其是在处理大范围时。

range 对象专门实现了 __reversed__,以提供这种高效的反向迭代,而无需存储所有数字。

错误处理

当与非序列类型一起使用时,reversed 函数会引发 TypeError。 此示例显示了正确的错误处理。

errors.py
try:
    print(list(reversed(42)))
except TypeError as e:
    print(f"Error: {e}")  # 'int' object is not reversible

class NoReverse:
    pass

try:
    print(list(reversed(NoReverse())))
except TypeError as e:
    print(f"Error: {e}")  # 'NoReverse' object is not reversible

这些示例演示了 reversed 对不受支持的类型的行为。 没有 __reversed__ 或序列协议的非序列对象和对象会引发 TypeError

要使类与 reversed 一起使用,请实现 __reversed__ 或序列协议,如前所示。

性能注意事项

此示例将 reversed 的性能与反向迭代的替代方法进行比较。

performance.py
import timeit

def test_reversed():
    return list(reversed([1, 2, 3, 4, 5]))

def test_slice():
    return [1, 2, 3, 4, 5][::-1]

def test_manual():
    lst = [1, 2, 3, 4, 5]
    return [lst[i] for i in range(len(lst)-1, -1, -1)]

print("reversed():", timeit.timeit(test_reversed, number=1000000))
print("slice:", timeit.timeit(test_slice, number=1000000))
print("manual:", timeit.timeit(test_manual, number=1000000))

这会衡量不同的反向迭代方法。 对于迭代,reversed 通常是最快的。 切片会创建一个新列表,但对于小序列来说速度很快。

手动方法较慢且可读性较差,这说明了为什么在迭代场景中首选 reversed

最佳实践

资料来源

作者

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

列出所有 Python 教程