返回小栈
关于python迭代器学习
bq_wang2020-02-19 10:03:56

python迭代器是个比较绕的概念,一遍示例一遍领悟,无他

⽣成器也是⼀种迭代器,但是你只能对其迭代⼀次。

这是因为它们并没有把所有的值存在内存中,⽽是在运⾏时⽣成值。

你通过遍历来使⽤它们,要么⽤⼀个“for”循环,要么将它们传递给任意可以进⾏迭代的函数和结构。

⼤多数时候⽣成器是以函数来实现的。然⽽,它们并不返回⼀个值,⽽是yield(暂且译作“⽣出”)⼀个值。

⽣成器最佳应⽤场景是:你不想同⼀时间将所有计算出来的⼤量结果集分配到内存当中,特别是结果集⾥还包含循环。


#fibon函数,通过数值交换实现
def fibon(n):
    a = b = 1
    for i in range(n):
        yield a
        a, b = b, a + b

gen = fibon(5)
print(next(gen))    #1
print(next(gen))    #1
print(next(gen))    #2
print(next(gen))    #3
print(next(gen))    #5
#print(next(gen))   #STraceback (most recent call last):   topIteration

for x in fibon(5):
     print(x)       #1  1   2   3   5

#文件读写的两种方法,一种是通过捕捉异常的方式,一种是通过判断尾行的方式
def file_next1(filename):
    with open(filename) as f:
        try:
            while True:
                line = next(f)
                print(line, end='')
        except StopIteration:
            pass

def file_next2(filename):
    with open(filename) as f:
        while True:
            line = next(f, None)
            if line is None:
                break
            print(line, end='')

file_next1('C:\Python\Pycharm/english.txt')
print('\n\r')
file_next2('C:\Python\Pycharm/english.txt')
print('\n\r')

#list通过iter进行迭代转换
items=[1,2,3]
item=iter(items)
next(item)  #1
next(item)  #2
next(item)  #3
#next(item)  #Traceback (most recent call last): StopIteration

#通过迭代器实现浮点数的步增
def frange(start, stop, increment):
    x = start
    while x < stop:
        yield x
        x += increment

#关于节点类的简单实现
class Node:
    def __init__(self, value):
        self._value = value
        self._children = []
    # 实例化输出实现
    def __repr__(self):
        return 'Node({})'.format(self._value)
    # 增加子节点
    def add_child(self, node):
        self._children.append(node)
    # 迭代器实现
    def __iter__(self):
        return iter(self._children)
    #深度优先
    def depth_first(self):
        yield self
        for c in self:
            yield from c.depth_first()
    #广度优先
    def width_first(self):
        if not (self._children is None or self._children==[]):
            #yield self._children   输出格式不对
            for c in self._children:    #先输出本层叶子节点
                yield c
            for c in self:              #再进行递归
                yield from c.width_first()

#通过__reversed__迭代器实现反向迭代
class Countdown:
    def __init__(self, start):
        self.start = start
    # 正向迭代 
    def __iter__(self):
        n = self.start
        while n > :
            yield n
            n -= 1
    # 反向迭代
    def __reversed__(self):
        n = 1
        while n <= self.start:
            yield n
            n += 1

if __name__ == '__main__':
    print('-------------')
    print(frange(1.04.50.8))    #<generator object frange at 0x0000023559D22660>
    for i in frange(1.04.50.8):
        print(i)                    #1.0,1.8,2.6,3.4,4.2

    a = [1234]
    for x in reversed(a):   #4  3   2   1
        print(x)

    print('-----------------')
    root = Node()
    child1 = Node(1)
    child2 = Node(2)
    root.add_child(child1)
    root.add_child(child2)
    child1.add_child(Node(3))
    child1.add_child(Node(4))
    child2.add_child(Node(5))
    print(root)     #Node(0)
    #print(item(root))   #TypeError: 'list_iterator' object is not callable
    #print(next(root))   #TypeError: 'Node' object is not an iterator
    print(root._children)   #[Node(1), Node(2)]
    print(root.__iter__())  #<list_iterator object at 0x000002707097DC50>
    # 对迭代器进行迭代
    list=iter(root.__iter__())
    for ch in root:
        print(ch)   #Node(1)    Node(2)
    print(root.__iter__())  # <list_iterator object at 0x000002707097DC50>
    # 对子节点进行迭代
    list = iter(root._children)
    for ch in root:
        print(ch)  # Node(1)    Node(2)
    # 对root.__iter__进行遍历,内部已迭代
    for ch in root:         #def __iter__(self):
        print(ch)   #Node(1)    Node(2)
    # 对子节点进行遍历
    for ch in root._children:
        print(ch)   #Node(1)    Node(2)
    #深度优先遍历
    print('深度优先遍历')
    for ch in root.depth_first():
        print(ch)   #Node(0)    Node(1) Node(3) Node(4) Node(2) Node(5)
    #广度优先遍历
    print('广度优先遍历')
    print(ro#广度优先遍历
    print('广度优先遍历')
    print(root)
    for ch in root.width_first():
        print(ch)   #Node(0)    Node(1) Node(1) Node(3) Node(4) Node(5)
    #通过reversed实现反向迭代
    print('------------------')
    for rr in reversed(Countdown(5)):   #1  2   3   4   5
        print(rr)
    for rr in Countdown(5):             #5  4   3   2   1
        print(rr)


1
0