python's docs

2.4.0 如何进行逆序迭代


0. 目标

实现一个连续浮点数发生器FloatRange(和xrange类似),根据给定的范围(start, end)和步进值(step)产生的一些连续浮点数,如迭代FloatRange(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


1. 序列如何逆序迭代

其实序列的逆序迭代主要在于如何将序列逆序

1)

# 1. 使用序列的逆序方法
>>> l = [1, 2, 3, 4, 5]

>>> l.reverse()

>>> l
[5, 4, 3, 2, 1]
# 但是问题是,这样会改变原列表的值

# 2. 使用逆向切片的方法
>>> l = [1, 2, 3, 4, 5]

>>> l[::-1]
[5, 4, 3, 2, 1]
# 问题在于这样相当于创建了一个新列表,同样会浪费内存

# 3. 使用reversed方法
>>> reversed(l)
<listreverseiterator at 0x7fa03c26f3d0>

>>> list(reversed(l))
[5, 4, 3, 2, 1]

>>> list(iter(l))
[1, 2, 3, 4, 5]
# 其实reversed()跟iter()函数只是顺序相反

2. 如何构造一个逆序迭代器

reversed()可以返回一个对象的逆序迭代器,和iter()不同的是,逆序迭代器,必须要求可迭代对象拥有__reversed__方法

class FloatRange(object):
    def __init__(self, start, end, step=0.1):
        self.start = start
        self.end = end
        self.step = step

    def __iter__(self):
        t = self.start
        while t <= self.end:
            yield t
            t += self.step

    def __reversed__(self):
        t = self.end
        while t >= self.start:
            yield t
            t -= self.step


if __name__ == "__main__":
    for i in FloatRange(1.0, 4.0, 0.5):
        print i

    for x in reversed(FloatRange(1.0, 4.0, 0.5)):
        print x

执行过程

python /tmp/test.py
1.0
1.5
2.0
2.5
3.0
3.5
4.0
4.0
3.5
3.0
2.5
2.0
1.5
1.0