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用于替代被装饰的类,并返回新的内嵌类。在实例化普通类的时候得到的就是被装饰器装饰后的类。