迭代器,生成器,列表推导式,生成器表达式

迭代器:

可迭代对象:内部含有__inter__的

可迭代对象不能取值,因为内部没有__next__()方法

可迭代对象------>迭代器:

  boj.__iter__()或者inter(obj)

实现的原理类似于往弹匣里面装子弹,然后一个一个往外发射

通过__iter__()来获取到迭代器

1 stes = {1, 2, 3, 4, 5, 67, 7}
2 print(stes.__dir__())
3 s = stes.__iter__()
4 print(s)
迭代器

打印结果

1 ['__repr__', '__hash__', '__getattribute__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__iter__', '__init__', '__sub__', '__rsub__', '__and__', '__rand__', '__xor__', '__rxor__', '__or__', '__ror__', '__isub__', '__iand__', '__ixor__', '__ior__', '__len__', '__contains__', '__new__', 'add', 'clear', 'copy', 'discard', 'difference', 'difference_update', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', '__reduce__', 'remove', '__sizeof__', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update', '__doc__', '__str__', '__setattr__', '__delattr__', '__reduce_ex__', '__subclasshook__', '__init_subclass__', '__format__', '__dir__', '__class__']
2 <set_iterator object at 0x0000000001EF1480>
打印结果

通过__next__()来拿到元素,一次只能拿一个,如果最后一个元素之后继续使用__next__(),会报错:StopIteration

 1 stes = {1, 2, 3, 4, 5, 67, 7}
 2 s = stes.__iter__()
 3 print(s.__next__())
 4 print(s.__next__())
 5 print(s.__next__())
 6 print(s.__next__())
 7 print(s.__next__())
 8 print(s.__next__())
 9 print(s.__next__())
10 print(s.__next__())
__next__()

打印结果为:

 1 1
 2 2
 3 3
 4 4
 5 5
 6 67
 7 7
 8 Traceback (most recent call last):
 9   File "C:/Python/Module/regex_test.py", line 53, in <module>
10     print(s.__next__())
11 StopIteration
打印结果

判断是否为迭代器:

  1.通过__iter__(),__next__()是否在obj.__dir__()

1 with open('01','w', encoding='utf-8') as f:
2     print('__iter__' in dir(f))
3     print('__next__' in dir(f))
4 """
5 打印结果:
6 True
7 True
8 说明文件句柄本身是一个迭代器
9 """
dir方法

  2.通过collections模块中的Iterable来判断

 1 from collections import Iterable
 2 from collections import Iterator
 3 
 4 l = [1,2,3,4]
 5 print(isinstance(l, Iterable))    # 判断是否为可迭代对象
 6 print(isinstance(l, list))
 7 
 8 
 9 """
10 打印结果:
11 True
12 True
13 """
14 
15 l = [1,2,3,4]
16 print(isinstance(l, Iterable))
17 print(isinstance(l, Iterator))
18 print(isinstance(l, list))
19 
20 """
21 打印结果:
22 True
23 False
24 True
25 """
Iterable

 

生成器:

生成器实质就是迭代器,在python中有三种方式来获取生成器:

1. 通过生成器函数
2. 通过各种推导式来实现来生成器
3. 通过数据的转换也可以获取生成器

 生成器是我们自己用Python代码写的迭代器:

 1 def gener():
 2     print(111)
 3     yield 222
 4     print(333)
 5     yield 444
 6     print(555)
 7     yield 666
 8     print(777)
 9     yield 888
10 
11 
12 gen = gener()
13 print(gen)
14 
15 # 打印结果为:<generator object gener at 0x0000000001E74D00>
生成器

生成器函数和普通的函数的区别就是把return换成了yield

 yield 和return区别

  1. 如果函数中包含了yield, 这个函数是一个生成器函数. 执行函数的时候是: 生成器

  2. 生成器执行__next__(). 执行到下一个yield

  3. yield的作用和return基本相同. 但是,只负责返回. 不会结束函数

  4. return,结束函数.

通过obj__next__()方法取值:

 1 def gener():
 2     print(111)
 3     yield 222
 4     print(333)
 5     yield 444
 6     print(555)
 7     yield 666
 8     print(777)
 9     yield 888
10 
11 
12 gen = gener()
13 print(gen)
14 ret = gen.__next__()    # 这里的ret相当于执行函数,直行道yield是返回yield的返回值
15 print(ret)
16 ret1 = gen.__next__()    
17 print(ret1)
18 ret2 = gen.__next__()    
19 print(ret2)
20 ret3 = gen.__next__()    
21 print(ret3)
22 
23 """
24 打印结果:
25 <generator object gener at 0x0000000000814D00>
26 111
27 222
28 333
29 444
30 555
31 666
32 777
33 888
34 """
生成器取值

生成器还可以通过send()方法进行取值个传值,不过使用send方法时要注意的是:

  1.第一个yield必须通过__next__()方法取得

  2.最后一个yield不能通过send()方法传值.

 1 def gener():
 2     print(111)
 3     a = yield 222
 4     print(a)
 5     print(333)
 6     b = yield 444
 7     print(b)
 8     print(555)
 9     c = yield 666
10     print(c)
11     print(777)
12     yield 888
13 
14 
15 gen = gener()
16 print(gen)
17 ret = gen.__next__()    
18 print(ret)
19 ret1 = gen.send('<<>>')    
20 print(ret1)
21 ret2 = gen.send('<<>>')    
22 print(ret2)
23 ret3 = gen.send('<<>>')    
24 print(ret3)
25 
26 """
27 打印结果:
28 <generator object gener at 0x0000000001DD4D00>
29 111
30 222
31 <<>>
32 333
33 444
34 <<>>
35 555
36 666
37 <<>>
38 777
39 888
40 """
send()方法

使用send()方法时要注意的是要传参,不然会报错

send和__next__() 区别:

  send可以给上一个yield 的位置传递值 , 第一个必须用__next__()

  __next__() 不能传值

列表推导式:

需要一个列表,里面包含1到13的数字,第一反应是:

1 l = []
2 
3 for i in range(1, 14):
4     l.append(i)
5 print(l)
6 # 打印结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
生成一个列表

 我们来看这样一段代码:

1 l = [ i for i in range(1,14)]
2 print(l)
3 
4 #打印结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
列表推导式

有这样一个需求,通过列表推导式来筛选憨厚两个e的名字:

1 names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
2          ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
3 name2 = [name for i in names for name in i if name.count('e') == 2]
4 print(name2)
5 
6 # 打印结果:['Jefferson', 'Wesley', 'Steven', 'Jennifer']
筛选模式

l = [变量(加工后的变量) for 变量 in iterable] 循环模式

l = [变量(加工后的变量) for 变量 in iterable if 条件] 筛选模式

类似于真样的式子被成为列表推导式.

优点:

1,节省代码,一行搞定.

2,看着高大上.

缺点:

不好排错.

整体:

凡是用列表推导式构造的列表对象,用其他方式都可构建.,非常复杂的列表,列表推导式是构建不出的,

列表推导式比较有魔性.

生成器表达式:

生成器表达式和列表推导式基本一样,唯一的区别就是把列表推推导式的方括号变成圆括号:

1 l = ( i for i in range(1,14))
2 print(l)
3 
4 #打印结果:<generator object <genexpr> at 0x0000000001F24D00>
生成器表达式

 

同样的也有两种模式:

循环模式和筛选模式

 

posted @ 2018-07-14 15:58  咕咚!  阅读(361)  评论(0编辑  收藏  举报