美文网首页
python生成器和迭代器

python生成器和迭代器

作者: Cache_wood | 来源:发表于2021-12-01 09:34 被阅读0次

    @[toc]

    观察者模式

    亦称
    – 发布(publish )-订阅(Subscribe)模式
    – 模型-视图(View)模式
    – 源-收听者(Listener)模式
    – 从属者模式

    要义
    – 一个目标对象管理所有依赖于它的观察者对象,并且在它本身的状态改变时主动发出通知
    – 观察者模式完美地将观察者和被观察的对象分离

    • 优点
      – 观察者与被观察者之间抽象耦合
      – 可以触发多个符合单一职责的模块
      – 可以很方便地实现广播
    • 场景
      – 消息交换,如消息队列;
      – 多级触发,如一个中断即会引发一连串反应
    • 缺点
      – 效率不一定高
    import time
    class Investor:
        def __init__(self,name,stock):
            self._name=name
            self._stock=stock
    
        @property
        def stock(self):
            return self._stock
        @stock.setter
        def stock(self,value):
            self._stock=value
    
        def update(self):
            print("{} invest on {} with price {}: sell it now!!!".format(self._name,self._stock.name,self._stock.price))
    
    class Stock:
        def __init__(self,name,price):
            self._name=name
            self._price=price
            self._investors=[]
    
        @property
        def name(self):
            return self._name
        
        @property
        def price(self):
            return self._price
    
        @price.setter
        def price(self,value):
            if self._price>value:
                self.notify()
            self._price=value
        
        def attach(self,investor):
            self._investors.append(investor)
    
        def notify(self):
            for investor in self._investors:
                investor.update()
    
    def main():
        s=Stock('区块链',11.11)
        i1=Investor('zjc',s)
        i2=Investor('lys',s)
        s.attach(i1)
        s.attach(i2)
        s.price=13
        time.sleep(1)
        s.price=10
    
    if __name__=='__main__':main()  
    
    zjc invest on 区块链 with price 13: sell it now!!!
    lys invest on 区块链 with price 13: sell it now!!!
    

    迭代

    • 通过 for … in 等遍历数据结构如tuple,list,dict字符串等
    • 判断一个对象是否可迭代
    from collections import Iterable
    isinstance([1,2,3],Iterable)
    
    • 同时迭代序号和元素
    for i,value in enumerate(['A','B','C']):
        pass
    

    生成器

    • 通过列表推导式构建生成器
    L = [x*x for x in range(10)] #列表
    G = (x*x for x in range(10)) #生成器
    
    • 通过next()函数获得generator的下一个返回值

    • 通过for … in 进行遍历

    • 通过定义函数构建生成器

      • 函数定义需要包含yield关键字
      • 在执行中遇到yield会中断,下次继续执行
        暂停并保存当前所有运行信息,返回yield的值,并在下一次执行next()方法时从当前位置继续运行
    • 获取返回值需要捕获StopIteration异常

    • 注意区分普通函数和generator函数

    • 普通函数调用直接返回结果

    • generator函数的调用实际返回一个generator对象

    def fib(max):
        n,a,b=0,0,1
        while(n<max):
            yield b
            a,b=b,a+b
            n+=1
        return 'done'
    
    print(fib(6))
    
    <generator object fib at 0x000001E77234AB30>
    #生成器不会直接直接打印出值,只会一个个加载
    
    for f in fib(6):
        print(f)
    1
    1
    2
    3
    5
    8
    #循环打印出值,但是不会出'done'
    
    f=fib(6)
    while True:
        try:
            print(next(f))
        except StopIteration as si:
            print(si.value)
            break
    1
    2
    3
    5
    8
    done  #这种方法可以打印出'done'
    
    from collections import Iterable
    #flatten函数用来展平
    def flatten(items,ingore_types=(str,bytes)):
        for x in items:
            if isinstance(x,Iterable) and not isinstance(x,ingore_types):
                yield from flatten(x,ingore_types)
            else:
                yield x
    
    items=[1,2,[3,4,5],[6,7],[[[8]]],9,10]
    finput=list(flatten(items))  #转化为列表
    print(finput)
    #for x in flatten(items):
    #   print(x)
    
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    迭代器

    • 可以被next()函数调用并不断返回下一个值的对象称为迭代器
    • 迭代器可以记住遍历位置
    • 迭代器只能往前不能后退(“消耗”数据)
    • 可以使用isinstance()判断一个对象是否是Iterator对象
    isinstance((x for x in range(10)),Iterator)
    
    • 生成器都是迭代器,但是list,dict,str虽然是Iterable,却不是Iterator
    • list,dict,strIterable变成Iterator可以使用iter()函数
    • Iterator对象表示一个数据流
      next()函数调用并不断返回下一个数据在,直到没有数据抛出StopIteration错误
      可将该数据流看作是长度未知的有序序列,只能不断通过next()函数实现按需计算下一个数据
      可表示无限大数据流,例如全体自然数,而使用list等不可能存储全体自然数
    创建迭代器
    • iter()函数
    • 把一个类作为一个迭代器使用需要在类中实现两个方法__iter__()__next__()
    • __iter__()返回一个特殊的迭代器对象,这个对象实现了__next__()方法
    • __next__()方法返回下一个元素并通过StopIteration异常标识迭代的完成
    from typing import Iterator
    
    class Numbers:
        def __init__(self,start=1,step=1,max=100):
            self._start=start
            self._step=step
            self._max=max
            self._a=self._start
            #self._list=[]
    
        def __iter__(self):
            
            return self
            #return iter(self._list)
    
        def __next__(self):
            if self._a <= self._max:
                x = self._a
                self._a += self._step
                return x
            else:
                raise StopIteration('大于max:{}'.format(self._max))
    
    num=Numbers(start=2,step=2,max=100)
    myiter=iter(num)
    
    for i in range(10):
        print(next(myiter))
    
    2
    4 
    6 
    8 
    10
    12
    14
    16
    18
    20
    
    迭代器相关工具

    相关文章

      网友评论

          本文标题:python生成器和迭代器

          本文链接:https://www.haomeiwen.com/subject/cgldxrtx.html