python迭代器,生成器,装饰器


一、迭代器

  迭代器从表面上看是一个数据流对象或容器,当使用其中的数据时,每次从数据流中取一个数据,直到数据被取完,而且数据不会被重复使用

__iter__():

__next__():

"__iter__()"方法返回对象本身,它是for语句使用迭代器的要求

"__next__()"方法用于返回容器中下一个元素或数据,当容器中的数据用尽时,应该引发StopIteration异常

  任何一个类,只要它实现了或具有这两个方法,就可以称其为迭代器,也可以说是迭代的。在使用它作为迭代器时,就可以用for来遍历(迭代)它,示例代码如下

for item in iterator:

  pass

  每个循环中,for语句都会从迭代器的序列中取一个数据,并赋值给item,供循环内使用或处理。从形式上完全与遍历元组,列表,字符串,字典等序列一样class MyIterator: #自定义类迭代器MyIterato    def __init__(self,x=2,xmax=100): #定义构造方法,初始化实例属性

class MyIterator:                                      #自定义类迭代器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                    #一定要raise或asrest等引 StopIteration 错误
        else:
            raise StopIteration                

if __name__ =='__main__':
    myiter = MyIterator()                             #实例化迭代器MyIterator
    for i in myiter:                                    #遍历并输出值
        print('迭代的数据元素为:',i)



#执行结果

迭代的数据元素为: 4
迭代的数据元素为: 8
迭代的数据元素为: 16
迭代的数据元素为: 32
迭代的数据元素为: 64

【代码说明】

  从代码中可以看出,如果需要产生很大范围的数的序列,采用列表或元组等进行一次性生成,则必须会占据大量

的内存空间,对系统有很大的“杀伤力”。而使用了迭代器,则可以每次调用时生成一个,显然可以节约大量的内存空间。

二、生成器

  生成器对象是通过使用yield关键字定义的函数,因此,生成器也是一个函数。生成器用于生成一个值的序列,以便在迭代中使用

  yield关键字,先返回一个值,然后停止,在下一次运行的时候,在停止的这个位置继续运行

  return 是函数返回后,直接退出函数,yield包含return功能,但不退出函数,下次直接在yield下一句语句执行

def myYield(n):                             #定义一个生成器(函数)
    while n < 5:
        print('start')
        yield n                             #yield这一步就开始返回n的值了,在进入下一步从print('one...')开始执行
        print('one...')
        n += 1

if __name__ == '__main__':
    for i in myYield(1):                    #for循环遍历生成器
        print('遍历得到的值:',i)
    print()
    my_yield = myYield(0)                   #生成一个生成对象
    print('已经实例化生成器对象')
    print(my_yield.__next__())              #手工调用其特殊方法,获取序列中一个值
    print(my_yield.__next__())              #第二次手工调用,继续输出yield之后的输出


#执行结果
start
遍历得到的值: 1
one...
start
遍历得到的值: 2
one...
start
遍历得到的值: 3
one...
start
遍历得到的值: 4
one...

已经实例化生成器对象
start
0
one...
start
1

【代码说明】

  生成器中包含yield语句,可以用for直接遍历,也可以手工调用其__next__()方法进行遍历

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

生成器与协程

  运用send()方法来重置生成器的生成序列,可以发送数字字符串等

  

def consumer():                                     #定义一个消费者模型(生成器协程)
    print('等待接收处理任务。。。')
    while True:
        data = (yield)
        print('收到任务:',data)                      #模拟接受并处理任务
                                                    #此处可以调用函数来完成任务
def producer():                                     #定义一个生产者模型
    c =consumer()
    c.__next__()
    for i in range(3):
        print('发送一个任务。。。','任务%d' %i)
        c.send(1)                                   #发送数字“1”
        c.send('任务%d' %i)                          #发送字符串

if __name__ == '__main__':
    producer()                                      #调用函数producer
    
    
#执行结果    


等待接收处理任务。。。
发送一个任务。。。 任务0
收到任务: 1
收到任务: 任务0
发送一个任务。。。 任务1
收到任务: 1
收到任务: 任务1
发送一个任务。。。 任务2
收到任务: 1
收到任务: 任务2

【代码说明】

  代码中通过定义的两个函数分别代表生成者和消费者模型,而其中的消费者模型实际是一个生成器。在生成者模型函数中每个循环模拟发送一个任务给消费者模型(生成器),而生成器则可以调用相关函数来处理任务,这就是运用yield语句的“hold”性质来完成这一项任务

装饰器:

  装饰器是一种增加函数或类的功能的简单方法,它可以快速地给不同的函数或类插入相同的功能,从本质上说,它是一种代码实现方式。

 实例:装饰函数

def abc(fun):                               #定义一个装饰abc
    def wrapper(*args,**kwargs):            #定义包装器函数
        print('start...')
        fun(*args,**kwargs)                 #调用被装饰器
        print('end...')
    return wrapper                          #返回包装器函数

@abc                                        #装饰函数语句
def demo_decoration(x):                     #定义普通函数,被装饰器装饰
    a = []
    for i in range(x):
        a.append(i)
    print(a)

@abc
def hello(name):                            #定义普通函数,被装饰器装饰
    print('Hello',name)

if __name__ == '__main__':
    demo_decoration(5)                      #调用被装饰器装饰的函数
    print()
    hello('XP')                             #调用被装饰器装饰的函数



#执行结果
start...
[0, 1, 2, 3, 4]
end...

start...
Hello XP
end...

【代码说明】

  代码中首先定义了一个装饰器函数(abc),它带有一个可以使用函数对象的参数,接着定义了两个被装饰器装饰的普通函数(demo_decoration,hello)。最后对被装饰器的函数进行调用。由此可见,调用被装饰器的函数,与调用普通函数没有任何区别,而在装饰器定义的内部,很明显又定义了一个内嵌的函数(wrapper),在这个内嵌的函数中执行了其他的一些语句,也调用了被装饰的函数。最后返回了这个内嵌的函数,代替了被装饰的函数,从而完成了装饰器的功能。

实例:装饰类

  装饰器不仅可以装饰函数,也可以装饰类。定义装饰类的装饰器,采用的方法是:定义内嵌类的函数,并返回新类

def abc(myclass):                                   #定义装饰器
    class InnerClass:                               #定义嵌套的类
        def __init__(self,z=0):
            self.z = 0
            self.wrapper = myclass()                #实例化被装饰的类

        def position(self):
            self.wrapper.position1()                #调用被装饰类的方法
            print('z axis:',self.z)

    return InnerClass                               #返回新定义的类

@abc                                                #应用装饰器
class coordination:                                 #定义普通的类
    def __init__(self,x=0,y=0):
        self.x = x
        self.y = y

    def position1(self):
        print('x axis:',self.x)
        print('y axis:',self.y)

if __name__ == '__main__':
    coor = coordination()                           #实例化被装饰的类
    coor.position()                                 #调用类中的方法position()


#执行结果

x axis: 0
y axis: 0
z axis: 0

【代码说明】

  代码中首先定义了一个能够装饰类的装饰器abc,在其中定义了一个内嵌类InnerClass,用于代替被装饰的类,并放回新的内嵌类。而在实例化普通类时,得到的就是被装饰器装饰过后的类