zoukankan      html  css  js  c++  java
  • 迭代器、生成器、装饰器(9)

    第9章 迭代器、生成器、装饰器
    迭代器:迭代器是一个数据流对象和容器,当使用其中的数据时,每次从数据流中取一个数据,直到数据被取完,而且数据不会被重复使用。

    从代码角度将讲:迭代器是实现了迭代器协议方法的对象或类。
    迭代器
    协议方法:
    __iter__()  ,返回对象本身,是for语句使用迭代器的要求
    __next__()   ,返回容器中下一个元素或数据,当容器中的数据用尽时,应该引发StopIterator异常

    可以使用for循环遍历
    for item in iterator

    迭代器的优点:节约内存

    自定义迭代器:实现协议方法
    class MyIterator:
       def __init__(self,x=2,xmax=100):
           self.__mul,self.__x=x,x
           self.__xmax=xmax
       def __iter__(self):
           return self
       def __next__(self):
          if self.__mul and self.__x!=1:
              self.__mul*=self.__x
              if self.__mul<=self.__xmax:
                   return self.__mul
              else:
                 raise StopIteration
          else:
              raise StopIteration

    if __name__=='__main__':
        myiter=MyIterator()
        for i in myiter:
            print('迭代的数据元素为:',i)

    内置迭代器工具:
    1.内建迭代函数iter()
    iter(iterable)   #参数为可迭代的类型,包括序列
    iter(callable,sentinel)    #callable是可调用类型,一般为函数;sentinel为"哨兵",即当callable调用的返回值等于第二个参数的值时,迭代或遍历停止

    例子:
    class Counter:
        def __init__(self,x=0):
            self.x=x
    counter=Counter()
    def used_iter():
        counter.x+=2
        return counter.x
    for i in iter(used_iter,8):
        print('本次遍历的值:',i)

    2.itertools模块中常用工具函数
    count(start)   #start开始,计数迭代
    cycle(seq)        #循环迭代序列seq
    以上两中无限迭代器使用时,必须有迭代退出的条件,否则会有死循环
    repeat(elem[,n])   #循环迭代elem,n为迭代次数
    chain(p,q,....)    #将p,q连接起来迭代,就像从一个序列中迭代
    dropwhile(pred,seq)   #当pred对序列元素处理结果为假时开始迭代seq后所有值
    takewhile(pred,seq)   #取值与dropwhile相反
    filterfalse(pred,seq)   #当pred处理为假的元素
    tee(it,b)      #将it重复n次进行迭代(嵌套for循环)
    permutations(p,r)   #迭代序列中r个元素的排列
    combinations(p,r)    #迭代序列中r个元素的组合


    生成器
    使用生成器,可以生成一个值的序列用于迭代,并且这个值的序列不是一次生成的,而是使用一个,再生成一个,可以节约大量内存

    生成对象可以直接被for遍历,也可以手工进行遍历
    例子:
    def myYield(n):
        while n>0:
        print("开始生成:....")
        yield n
        print("完成一次....")
        n-=1
    if __name__=='__main__':
        for i in myYield(4):
            print("遍历得到的值:",i)
        print()
        my_yield=myYield(3)
        print('已经实例化生成器对象')
        my_yield.__next__()
        print('第二次调用__next__()方法:')
        my_yield.__next__()                           #__next__()函数的返回值是关键字yield后的n的值

    生成器在实例化时并不会立即执行,而是等待调用其__next__()才开始运行。
    当程序运行完yield语句后就会“hold住”,即保持其当前状态且停止运行
    等待下一次遍历时才恢复运行,生成器的恢复运行是从yield语句之后开始运行的

    yield语句不仅可以使函数成为生成器和返回值,还可以接受调用者传来的数值。
    例:
    def myYield(n):
        while n>0:
            rcv=yield n
            n-=1
            if rcv is not None:
                n=rcv

    if __name__=='__main__':
        my_yield=myYield(3)
        print(my_yield.__next__())
        print(my_yield.__next__())
        print('传给生成器一个值,重新初始化生成器。')
        print(my_yield.send(10))
        print(my_yield.__next__())

    生成器的另一种表达式:a=i for i in range(5)   #推导最外层的括号去掉
    list(a)   把a这个生成器对象转化为列表
    注:如果生成器生成的序列是无限的或大量的序列,不可以将其转换为列表,否则会导致死机或大量消耗内存


    通过生成器实现协程
    例:生产者与消费者编程模型

    def consumer():
        print('等待接受处理任务...')
        while True:
            data=(yield)
            print('收到任务:',data)
    def producer():
        c=consumer()
        c.__next__()                                          #第一次调用生成器时不能传递给生成器None以外的值,否则会引发错误
        for i in range(3)
            print('发送一个任务....','任务%d'%i)
            c.send('任务%d'%i)
    if __name__=='__main__':
        producer()

    __next__()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而__next__()不能传递特定的值,只能传递None进去。因此,我们可以看做c.__next__() 和 c.send(None) 作用是一样的。

    装饰器
    装饰器是一种增加函数或类功能的简单方法,可以快速地给不同的函数或类插入相同的功能

    使用形式:
    @disp_run_time
    def decorated_fun():
        pass
    或嵌套装饰
    @abc
    @disp_run_time
    def decorated_fun():
        pass
    调用形式:
    decorated_fun()

    定义装饰器:
    def demo_decorater(fun):   #定义装饰器函数
        def new_fun(*args,**kwargs):   #新定义包装器函数
            pass
            fun(*args,**kwargs)          #包装器函数中调用被装饰的函数
            pass
        return new_fun                  #返回包装器函数

    装饰器也是可以带参数的:
    def abc(action):
        def mabc(fun):
            def wrapper(*args,**kwargs):                
                print('开始运行....',action)
                fun(*args,**kwargs)
                print('运行结束....',action)
            return wrapper
        return mabc


    定义装饰类的装饰器:定义内嵌类的函数,并返回新类
    例:
    def abc(myclass):
        class InnerClass:
            def __init__(self,z=0):
                self.z=z
                self.wrapper=myclass()
            def position(self):
                self.wrapper.position()
                print('z axis:',self.z)
        return InnerClass

    @abc
    class coordination:
        def __init__(self,x=0,y=0):
            self.x=x
            self.y=y
        def position(self):
            print('x axis:',self.x)
            print('y axis:',self.y)

    if __name__=='__main__':
        coor=coordination()
        coor.position()

    输出结果:
    x axis: 0
    y axis: 0
    z axis: 0

  • 相关阅读:
    IE8兼容
    游标
    WARN No appenders could be found for logger (org.springframework.orm.hibernate3.support.OpenSessionInViewFilter)
    sql server 备份数据
    JS页面打印
    jQuery Mobile 入门教程
    jquerymobile入门(文件引用+多页面)
    定位和可见性
    二月份总结
    mailto用法
  • 原文地址:https://www.cnblogs.com/MUMO/p/5761855.html
Copyright © 2011-2022 走看看