Python如何实现反向迭代
反向迭代通常是指从序列的末尾开始进行迭代。那么在Python中如何实现呢?
l = [1, 2, 3, 4, 5]
l.reverse()
print(l) #[5, 4, 3, 2, 1]
看上面这个列表,怎么反向输出呢,首先可以想到列表的 reverse 方法,然后再迭代 list 是不是就实现了反序,但是有一个问题,就是它改变了原来的列表,这在某些情况下是并不允许的。
l = [1, 2, 3, 4, 5]
l2 = l[::-1]
print(l2)
我们很快又想到了这种方法,切片操作,但是这样也有一个问题,这样我们就创建了一个和原列表等大的新列表,某种意义上这也是非常浪费资源的。
那我们到底如何实现反向迭代呢?其实python有一个内置函数 reversed() 。reversed操作会产生一个列表的反向生成器也可以实现反向迭代而且不占用存储空间。
reversed(sequence)
- sequence:要反转的序列。
- 返回一个反向迭代器对象。可以使用list()函数将其转换为一个列表。
下面看一下reversed函数的原理
l = [1, 2, 3, 4, 5]
print(iter(l)) #<list_iterator object at 0x000002C03B40B828>
print(reversed(l)) #<list_reverseiterator object at 0x000002C03B40B828>
我们看到它和 iter 相反,它的到的是一个反向迭代器。那什么可以使用 reversed 呢?需要它拥有 __reversed__ 这个方法,和 iter 方法 需要有 __iter__ 是一样的道理。所以 reversed 函数接收的参数,是一个实现了 __reversed__ 方法的序列对象,可以是字符串、列表、元组,也可以是自定义的。
下面写一个反向迭代的案例:
需求:实现一个连续浮点数发生器FloatRange(和range类似),根据给定范围(start,end)和步进值(step),产生一系列连续的浮点数;
如迭代FlartRange(3.0, 4.0, 0.2)可产生序列:
正向:3.0 -> 3.2 -> 3.4 -> 3.6 -> 3.8 -> 4.0
反向:4.0 -> 3.8 -> 3.6 -> 3.4 -> 3.2 -> 3.0
from decimal import Decimal
class FloatRange:
def __init__(self, a, b, step):
self.a = Decimal(str(a))
self.b = Decimal(str(b))
self.step = Decimal(str(step))
def __iter__(self):
t = self.a
while t <= self.b:
yield float(t)
t += self.step
def __reversed__(self):
t = self.b
while t >= self.a:
yield float(t)
t -= self.step