Python基础之迭代器与生成器

参考了《Python3从入门到实战》

一、迭代器

1.一个可迭代的队象的__iter()方法返回一个迭代器,而这个迭代器的__next()方法会返回可迭代对象的下一个元素
注:可迭代对象可以用for in 来进行输出,而迭代器要用next方法()

2.Python提供了两个对应的内置函数iter() 和 next() ,内置函数iter()作用于可迭代对象,会调用这个对象的__iter__()方法返回一个迭代器,而内置函数next()作用于这个迭代器,会调用这个的带起的__next()__方法返回可迭代元素的下一个元素

	alist = [1,3,5,19,7]
    it = iter(alist)#返回一个迭代器
    print(type(alist))
    print(type(it))
    print(next(it))#得到迭代器的下一个值
    运行结果如下:
    <class 'list'>
	<class 'list_iterator'>
	1

下列的类A实现了__iter__()方法,因此类A的对象就是一个可迭代对象,iter()的方法必须返回一个迭代器,即B类的对象必须是一个迭代器,也就是说类B必须实现__next__()方法

	import time
    class A(object):
        def __iter__(self):
            return B()
        
    class B(object):
        def __next__(self):
            return "hello"
        
    iterable = A()#可迭代对象   可迭代对象由下列方法进行迭代
    iterator = iter(iterable)#迭代器 迭代器用next方法
    
    #一直打印hello
    i = 0
    for e in iterable:
        print(e)
        time.sleep(1)
        print(i)
        i += 1

	运行结果如下:
	hello
	0
	hello
	1
	hello
	2
	hello
	3
	hello
	#需要自己按下停止按钮,这里没有设置什么时候停止,而是一个死循环
	class A(object):
        def __iter__(self):
            return B()
        
    class B(object):
        def __init__(self):
            self.i = 0
            self.data = [2,4,8]
        def __next__(self):
            if self.i == 3:#计数,到3就停止执行
                raise StopIteration()
            self.i += 1
            return self.data[self.i-1]#返回每个值
    
    iterable = A()
    for e in iterable:
        print(e,end=" ")

	运行结果如下:
	2 4 8 

3.通常,可迭代对象的所属类和迭代器的所属类并不是这样完全分离的,而是同一个类,这个类同时实现__iter__()和__next__()方法,因此这类的对象即使一个可迭代对象也是一个迭代器

	class X(object):
        def __init__(self):
            self.i = 0
            self.data = [2,4,8]
        def __iter__(self):
            return self
        def __next__(self):
            if self.i == 3:
                raise StopIteration()
            self.i += 1
            return self.data[self.i-1]
    b = X()
    
    it = iter(b)#得到迭代器
    
    print(next(it))
    #print(next(it))
    
    b2 = X()
    
    for i in b2:
        print(i)
    运行结果如下:
    2
	2
	4
	8

4.一个对象是可迭代的,除其所属类实现__iter__()方法,其所属类还可以实现__getitem__()方法

5.如果用for循环将输出无限循环,其第二个参数是一个键(关键字),对实现该方法的类对象obj,可以通过obj[key]来得到该键对应的值

	class Y:
        def __getitem__(self,i):
            return i * i
    y = Y()
    
    print(y[2])


	运行结果如下:
	4
	class MyDict:
        def __init__(self):
            self.dict = {
    
    }
        def __getitem__(self,key):
            return self.dict[key]
        def __setitem__(self,key,value):
            self.dict[key] = value
        def __len__(self):
            return len(self.dict)
    d = MyDict()
    d['李萍'] = 67.5#调用setitem方法
    print(d['李萍'])#调用getitem方法
    d['王伟'] = 77.5
    print(d['王伟'])
	运行结果如下:
	67.5
	77.5

二、生成器

1.生成器是一个用于创建迭代器的简单而强大的工具,又是一个可以产生一系列值的函数,生成器会记住上一次执行的语句,每当需要数据时,生成器都会从中断处继续,并通过yield语句产生一新的数据.因此生成器是一个特殊的迭代器,也是一个可迭代对象

生成器函数

	def gen(n):
        for i in range(n):
            yield(i)
    
    '''生成器会记住函数执行的状态,当再次调用__next__()方法时,
    会根据上次的位置和状态,继续执行,当再次遇到yield语句,
    又产生一个新的返回值并终止当前的执行.
    '''     
    g = gen(5)
    print(g.__next__())
    print(g.__next__())
    print(next(g))#也可以用这种方法(因为生成器也是迭代器)
    print(g)#g是一个生成器的对象
    print(type(g))
    #迭代
    g = gen(10)#生成器是一个可迭代对象
    for i in g:
        print(i)

	运行结果如下:
	0
	1
	2
	<generator object gen at 0x000002335EEF0A50>
	<class 'generator'>
	0
	1
	2
	3
	4
	5
	6
	7
	8
	9

2.包含return的函数当遇到return语句时,会停滞函数执行并返回,函数每次执行都是独立的,且是从头开始的,不会保存上一次执行的状态和位置

3.包含yield的生成器函数用于产生一系列值,每次执行当遇到yield语句会停止执行,并返回yield语句的结果,但内部会保留上一次执行的状态,下一次执行从上一次执行的yield之后的代码继续执行,直到再次遇到yield返回

4.生成器函数可以用来生成一系列的值,这些值没有保存的内存中,而是在需要的时候产生,这样可以节省很多内存

	#求1到10的整数和
    #生成器方法
    def gen(n):
        for i in range(n):
            yield i
            
    g = gen(11)#这是一个生成器
    
    sum = 0
    for e in g:
        sum += e
    print(sum)

	运行结果:
	55
	#用生成器产生斐波拉西数列
    def fib(M):
        n,a,b = 0,0,1
        while(n<M):
            yield b 
            a,b = b,a+b#这个是同时完成a=b,b=a+b
            n += 1
            
    for x in fib(8):
        print(x,end=" ")
	
	运行结果如下:
	1 1 2 3 5 8 13 21 

三、标准库的迭代工具

1.zip函数,该函数的输入参数是数目可变的任意多个可迭代对象,返回一个数据元素(tuple迭代器),每个tuple是由多个输入迭代器中对应的元素构成的

2.如果没有输入参数,则返回一个空的迭代器

3.如果输入一个可迭代对象,则返回一个数据元素(tuple的迭代器),每个tuple只有一个值

4.如果输入多个可迭代对象,则返回一个数据元素(tuple的迭代器),每个tuple由分别来自输入的可迭代对象的对象元素构成

5.zip对象是一个可迭代对象,因此可以用它构造一个list对象,但是不能用它构造一个tuple对象

	result = zip()
    print(list(result))
    alist = [1,2,3]
    result = zip(alist)
    for e in result:
        print(e,end=" ")
        
    print()
    str = ("许嵩","周杰伦","薛之谦")
    result = zip(alist,str)
    for e in result:
        print(e)


	运行结果如下:
	[]
	(1,) (2,) (3,) 
	(1, '许嵩')
	(2, '周杰伦')
	(3, '薛之谦')

	a = [1,2,3]
    b = ['a','b','c']
    c = zip(a,b)#用zip将a,b打包
    c = list(c)#要有这句话,否则报错
    for i in c:
        print(i)
        
    d,e = zip(*c)#用zip将a,b解包
    print(d,e)

	运行结果如下:
	(1, 'a')
	(2, 'b')
	(3, 'c')
	(1, 2, 3) ('a', 'b', 'c')

6.函数enumerate,输入一个可迭代对象,返回一个enumerate对象,该对象也是一个可迭代对象,其每个元素形如(index,value)

7.函数chain()返回将多个可迭代对象串联起来的可迭代对象

	import itertools#需要先导入这个模块
    it1 = [1,2,3]
    it2 = (2,3,4)
    it = itertools.chain(it1,it2)
    for e in it:
        print(e)
    运行结果如下:
    '''
    1
    2
    3
    2
    3
    4
    '''

8.函数count() 该函数返回一个迭代器,迭代器产生一个均匀的数字序列,该序列的开始值是start,两个相邻的差是step,这个序列是一个无限序列

	from itertools import count
    
    for i in count(10):#start=10 默认step=1
        if i > 20:
            break
        print(i)
    '''
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    '''

9.函数islice()也是itertools的一个函数,函数格式如下:

islice(iterable,stop)
islice(iterable,start,stop[,step])

该函数用于从可迭代对象中产生一个切片对象,其中,stop是切片的结束位置,start是开始位置,而step是步长

	from itertools import islice,count
    
    #2即是步长
    #count(10)是一个迭代器
    for i in islice(count(10),5,10,2):#第五个开始,到第十个,step=2
        print(i)

	运行结果如下:
    '''
    15
    17
    19
    '''

10.函数cycle()作用于一个可迭代对象,产生一个重复循环的iterable对象中值的迭代器

	from itertools import cycle
    count = 0
    for item in cycle('xyz'):
        if count > 9:
            break
        print(item,end=" ")
        count += 1
    '''
    x y z x y z x y z x 
    '''

11.#函数repeat该函数用于产生一个times个重复值为object的迭代器,它和函数cycle()的区别是,它只作用于一个有值的对象object,而函数cycle()作用于一个有多个值的可迭代对象

	from itertools import repeat
    
    r = repeat(7,3)#重复一个对象 多少次
    for i in r:
        print(i)
    '''
    7
    7
    7
    '''

总结:本文介绍了迭代器和生成器的使用,熟练掌握即可方便的迭代一些对象。

猜你喜欢

转载自blog.csdn.net/qq_45911278/article/details/111814446