python学习之迭代器、生成器和装饰器


1.迭代器表面上看是一个数据流对象或者容器,当使用其中的数据时,每次从数据流中取出一个数据,直到数据被取完,而且数据不会被重复使用。从代码的角度来看,迭代器是实现了迭代器协议方法的对象和类。迭代器协议方法主要是两个:
__iter__()#该方法返回对象本身,它是for语句使用迭代器的要求
__next__()#方法用于返回容器中下一个元素或者数据。当容器中的数据用尽时,应该引发StopIteration异常
任何一个类只要具有这两种方法,就可以称之为迭代器,也可以说是可迭代的。在它作为迭代器的时候就可以使用for循环来遍历它:
for item in iterator:
    pass
自定义一个迭代器,如下所示:
class my_iterator:
         def __init__(self,x,max):
                  self.mul,self.x=x,x
                  self.xmax=max
         def __iter__(self):
                  return self
         def __next__(self):
                  if self.x and self.x!=1:
                           self.mul=self.mul*self.x
                           if self.mul                                     return self.mul
                           else:raise StopIteration
if __name__=='__main__':
         myite1=my_iterator(2,100)
         for i in myite1:
                  print(i)
使用内置的迭代工具:python中已经内建了一个用于产生迭代器的函数iter(),另外标准库的itertools模块中还有丰富的迭代器工具。对于内建的迭代函数iter(),使用如下:
iter(iterable)#要求该参数是可迭代类型,也可以使用各种序列类型
iter(callable,sential)#第一个参数是可调用类型一般是函数,第二个参数是“哨兵”,用于遍历结束
示例如下:
class counter:
         def __init__(self,x=0):
                  self.x=x
counter1=counter()
def used_iter():
         counter1.x+=2
         return counter1.x
for i in iter(used_iter,8):
         print("current number",i)
         
2.生成器:使用生成器可以生成一个值的序列用于迭代,并且这个值的序列不是一次生成的,而是使用一个,再生成一个,可以使得程序节约大量内存。
生成器对象是通过yield关键字定义的函数对象,因此生成器也是一个函数。生成器用于生成一个值的序列,以便在迭代中使用。自定义生成器函数及使用如下:
def myyield(n):
         while n>0:
                  yield n
                  print("start yielding")
                  n-=1
                  print("finished it")


if __name__=='__main__':
         for i in myyield(4):
                  print("current number",i)
         myyield1=myyield(3)
         myyield1.__next__()#手工调用其特殊方法,获取序列中的一个值
         myyield1.__next__()
需要注意的是yield是生成器中的关键语句,生成器在实例化的时候并不会立即执行,而是等待调用其__next__()方法之后才开始运行。
yield语句不仅可以使得函数成为生成器和返回值,还可以接受调用者传来的值,如下:
def myyield(n):
         while n>0:
                  rcv=yield n #rcv接收调用者传来的值
                  n-=1
                  if rcv is not None:#rcv不为none的时候就重置n为rcv
                           n=rcv
if __name__=='__main__':
         my_yield=myyield(3)
         print(my_yield.__next__())
         print(my_yield.__next__())
         print("give a new number to generator")
         print(my_yield.send(10))
         print(my_yield.__next__())
但值得注意的是:第一次调用生成器时不能传给生成器none以外的值,否则会引发错误。
上面这段代码中用到的send()方法来重置生成器的生成序列,其实也称为协程,它是解决程序并发的方法。采用一般的方法实现消费者与生产者这个传统的并发程序设计问题,则要考虑的问题比较复杂,但是用生成器实现的协程解决问题就比较方便,如下所示:
def consumer():
         print("wait a misiion")
         while True:
                  data=(yield)
                  data=data-1
                  print('mission got',data)
def producer():
         c=consumer()
         c.__next__()
         for i in range (3):
                  print("give a mission",'mission%d'%i)
                  c.send('mission%d'%i)
if __name__=='__main__':
         producer()
该代码中通过两个函数分别代表生产者和消费者模型,而其中的消费者模型其实是一个生成器。在生产者模型函数中每个循环发送一个任务给消费者模型,而生成器可以调用相关的函数进行处理。这里主要是运用yield语句的hold特性实现的。
3装饰器:装饰器是一种增加函数或者类的功能的简单的方法,它可以快速地给不同的函数或者类插入相同的功能。从本质上来说,它是一种代码实现方式。
装饰器的表示语法是使用一个特殊的@来实现的。使用装饰器装饰函数的操作就是将“@装饰器名称”放在函数和类的定义行之前。装饰器既可以装饰函数,也可以装饰对象。
装饰器用来装饰函数,示例如下:
def abc(fun):#定义一个装饰器
         def wrapper(*args,**kwargs):#定义包装器函数
                  print("start running")
                  fun(*args,**kwargs)#调用被装饰函数
                  print("running finished")
         return wrapper
@abc#装饰函数语句
def hello(name):
         print("hello",name)
if __name__=='__main__':
         hello('ruirui')#调用被装饰器装饰的函数
装饰器用来装饰对象:定义内嵌类的函数并返回新类,示例如下:
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()
代码中首先定义了一个能够装饰类的装饰器abc,在其中定义了一个内嵌函数innerclass用于替代被装饰的类,并返回新的内嵌类。在实例化普通类的时候得到的就是被装饰器装饰后的类。

你可能感兴趣的:(python)