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

    一、迭代器:

    1、什么是迭代器?

          在python中,迭代器是一个可以记住遍历位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问完,迭代器只能往前不会后退。简单来讲我们见的比较多的是for 循环来遍历列表、元组、字符串等容器,这个就是迭代器的使用,所以说,迭代器简单可以理解成我们平时要从柜子里取东西时的动作。

    2、两个内置迭代器协议方法:

     a、方法iter():返回对象本身,是for循环语句使用迭代器的要求。

     b、方法next():用于返回容器中下一个元素(所谓容器,简单理解就是一个存储东西的柜子,要用的话,就可以拿出来,在python 中我们使用for语句来循环遍历来取出使用)或者数据,当使用完容器中的数据时就会引发StopIteration错误。

    3、创建并使用迭代器:

    复制代码
     1 class Use:    #定义了迭代器类
     2     def __init__(self,x=2,max=50):        #定义构造方法
     3         self.__mul,self.__x=x,x      #初始化私有的实例属性
     4         self.__max=max
     5     def __iter__(self):       #定义迭代器协议方法
     6         return self           #返回类的自身
     7     def __next__(self):       #定义迭代器协议方法
     8         if self.__x and self.__x != 1:
     9           self.__mul  *= self.__x
    10           if self.__mul <= self.__max:
    11               return self.__mul
    12           else:
    13               raise StopIteration
    14         else:
    15              raise StopIteration
    16 
    17 if __name__ == '__main__':
    18     my=Use()
    19     for i in my:
    20         print(i)
    21 
    22             
    复制代码

    注意:当在python 中使用迭代器类时,一定要在某个条件下引发StopIteration错误,这样可以结束遍历循环,否则会产生死循环

    4、使用内置迭代器方法iter():

    a、iter(iterable),只有一个参数iterable,要求参数为可迭代的类型,也可以使用各种序列类型,演示如下;

    list=[1,2,3,4]
    it = iter(list)  #创建迭代器对象
    for i in it:     #遍历 迭代器中的数据
        print(i)     #显示迭代效果

    b、iter(callable,sentinel),第一个参数callable表示可调用类型,一般为函数;第二参数sentine是一个标记,当第一个参数(函数)的返回值等于第二个参数的值时,迭代或者遍历会马上停止。演示如下:

    复制代码
    class Count:    #定义类Count
        def __init__(self,x=0):   # 定义构造方法
            self.x=x
    count = Count()
    def use_iter():
        count.x +=2
        return count.x
    for i in iter(use_iter,12):    #通过迭代遍历方法iter()产生的迭代器
        print(i)
    复制代码

    5、方法next()的使用:

    复制代码
    string='i like it'
    it = iter(string)
    while True:
        try:
            each=next(it) #读取字符中的每一个元素,并使用try  except 结构来检查是否有异常发生,当try里面出现异常时,就会执行下面的except的语句
        except StopIteration:
            break
        print(each)
    复制代码

    二、生成器:

    1、什么是生成器?

          在python 中,使用关键字yield定义的函数就称为生成器,通过使用生成器,可以生成一个值序列为用于迭代,并且这个值序列不是一次生成的,而是使用一个,再生成一个,最大的好处是可以使程序节约大量的内存。

    2、生成器的运行机制:

         在python程序中,生成器是一个记住上一次返回时在函数体中位置的函数,。对生成器函数的第二次(或第n次)调用,跳转至该函数中间,而上次调用的所有布局变量都保持不变。生成器不仅记住了它的数据状态,还记住了它在流控制构造(在命令式编程中,这种构造不只是数据值)的中的位置。

         生成器的特点如下:

               a、生成器是一个函数,而且函数的参数都会保留

               b、当迭代到下一次调用时,所使用的参数都是第一次所保留的。也就是说,在整个函数调用中的参数都是第一次所调用时保留的,而不是新创建的

          在python程序中,使用关键字yield定义生成器。当向生成器索要一个数时,生成器就会执行。直至出现yield语句时,生成器才把yield的参数传给你,之后生成器就不会往下继续运行。当向生成器索要一个数时,它会从上次的状态开始运行,直至出现yield语句时,才把参数传给你,然后停下,如此反复,直至退出函数为止

    3、使用yield生成器:

    复制代码
    def fib(max):
        a,b = 1,1
        while a < max:
            yield a   #程序运行到这里就不会往下继续执行了,所以第一次a =1,b=1,当第二次遍历函数时fib()时,a ,b 的值还是上次的值,而且会跳到这里,然后执行到下面的语句
            a,b = b,a+b
    for n in fib(15):
        print(n)     #这里打印的值其实是a的值
    复制代码

    执行结果:

    复制代码
    1
    1
    2
    3
    5
    8
    13
    复制代码

    说明:在Python中,当函数定义里面使用了关键字yield,那么这个函数就是一个生成器;它的执行会和其他普通的函数有很多不同,该函数返回的是一个对象,而不是像平常函数所用的return语句那样,能得到结果。如果想取得值,还需要调用next()函数。  

    4、创建生成器:

    复制代码
    def haha(n):
        while n > 0:
            print('开始生成......')
            yield n #定义一个生成器
            print('完成一次......')
            n -=1
    if __name__ == '__main__':     #当导入模块时不运行,否则会运行下面的代码
        for i in haha(4):
            print('遍历得到的值',i)
        print()
        tutu=haha(3)
        print('已经实例化生成器对象')
        tutu.__next__() #直接遍历自己创建的生成器
        print('第二次调用__next__()方法')
        tutu.__next__()  #以手工方式获取生成器产生的数值序列
    复制代码

    运行结果:

    复制代码
    开始生成......
    遍历得到的值 4
    完成一次......
    开始生成......
    遍历得到的值 3
    完成一次......
    开始生成......
    遍历得到的值 2
    完成一次......
    开始生成......
    遍历得到的值 1
    完成一次......
    

    已经实例化生成器对象
    开始生成......
    第二次调用__next__()方法
    完成一次......
    开始生成......

    复制代码

    注意:生成器在实例化时,不会立即执行,而是等候其调用方法__next__()才开始运行。

    三、装饰器:

    1、什么是装饰器?

          在python程序中,通过使用装饰器可以给函数或类增强功能,并且还可以快速地给不同的函数或类插入相同的功能,也就是说,装饰器是一种实现代码的实现方式

    2、创建装饰器

          要想在Python程序中使用装饰器,需要使用一个特殊的符号 "@" 来实现。在定义装饰器装饰函数时或类时,使用"@装饰器名称"的形式将符号 “@”放在函数或类的定义行之前。例如,有一个装饰器名称为"haha",当需要在函数中使用装饰器功能时,可以使用如下形式定义这个函数:

                        @  haha

                         def tutu():

                               pass

           在pytnon程序中使用装饰器后,上面的代码定义的函数tutu()可以只定义自己所需的功能,而装饰器所定义的功能会自动插入到函数中去,这样就可以节省大量具有相同功能的函数或类的代码。

    3、使用装饰器 装饰函数:

    复制代码
    def zz(fun):    #定义一个装饰器函数
        def hh(*args,**bian):  #这里第一个参数表示把args这个参数打包或者解包,第个参数是把传输进来的实参进行打包成字典的形
            print('开始运行...')
            fun(*args,**bian)    #使用被装饰函数
            print("运行结束。。。。")
        return hh
    @zz      #装饰函数语句
    def demo(x):   #定义普通函数,它被装饰器装饰
        a=[]       #定义空列表
        for i in range(x):
            a.append(i)    #将i添加到列表末尾
        print(a)
    @zz
    def hello(name):
        print('hello',name)
    if __name__ == '__main__':
        demo(5)
        print()
        hello('haha')
    复制代码

    执行结果:

    复制代码
    开始运行...
    [0, 1, 2, 3, 4]
    运行结束。。。。
    

    开始运行...
    hello haha
    运行结束。。。。

    复制代码

    总结:当一般函数被装饰器修饰时,会把装饰器函数的功能插入到普通函数中去。

    4、使用装饰器修饰类:

    复制代码
    def zz(myclass):    # 定义一个能够装饰类的装饰器zz
        class Haha:
            #定义一个内嵌类Haha来代替被装饰的类
            def __init__(self,z=0):
                self.z=0
                self.haha=myclass()
                #实例化被修饰的类
            def tutu(self):
                self.haha.tutu()
                print('z轴的坐标:',self.z)
        return Haha
    @zz
    class Hoho:
        def __init__(self,x=0,y=0):
            self.x=0
            self.y=0
        def tutu(self):
            print('x轴的坐标:',self.x)
            print('y轴的坐标:',self.y)
    if __name__ == '__main__':
        coor=Hoho()
        coor.tutu()
    复制代码

    运行结果:

    x轴的坐标: 0
    y轴的坐标: 0
    z轴的坐标: 0

    总结:用装饰器修饰类,和修饰函数类似,只是在创建装饰器里函数返回的类型不同而已。

    --- 转载自:https://www.cnblogs.com/1121518wo/p/11011574.html
  • 相关阅读:
    When to Partition a Table and an Index
    Hello, world
    提交
    SubmitOncePage:解决刷新页面造成的数据重复提交问题
    压缩ASP.NET中的ViewState
    asp.net千奇百怪的日历
    ICallbackEventHandler实现
    xml數據
    CrystalReports
    [转]Microsoft Visual Studio 2005中使用水晶报表
  • 原文地址:https://www.cnblogs.com/bqwzx/p/11013659.html
Copyright © 2011-2022 走看看