迭代器,生成器

一、迭代器

python 一切皆对象

能被for循环的对象就是可迭代对象

可迭代对象: str,list,tuple,dict,set,range

迭代器: f1文件句柄

 

dir打印该对象的所有操作方法

1 s = 'python'
2 print(dir(s))

执行输出:

['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

 

什么是可迭代对象:内部含有__iter__方法的对象就叫做可迭代对象
可迭代对象就遵循可迭代协议。

判断是都为可迭代对象

1 s = 'python'
2 print('__iter__' in dir(s))

执行输出:

True

 

迭代器

可迭代对象转化成迭代器:可迭代对象.__iter__() --->迭代器
迭代器不仅含有__iter__,还含有__next__。遵循迭代器协议。

1 l1 = [1,2,3]
2 l1_obj = l1.__iter__()  # 迭代器
3 print(l1_obj)

 

执行输出:

<list_iterator object at 0x000001987D5EB668>

表示它是一个列表迭代器对象

1 l1 = [1,2,3]
2 l1_obj = l1.__iter__()  # 迭代器
3 print('__iter__' in  dir(l1_obj)) #是否含有__iter__方法
4 print('__next__' in  dir(l1)) #是否含有__next__方法
5 print('__next__' in  dir(l1_obj))

执行输出:

True
False
True

从结果中,可以看出l1_obj是同时含有__iter__和__next__的对象,所以它是迭代器

迭代器使用__next__获取一个值

1 l1 = [1,2,3]
2 l1_obj = l1.__iter__()  # 迭代器
3 print(l1_obj.__next__()) #获取一个元素
4 print(l1_obj.__next__())
5 print(l1_obj.__next__())
6 print(l1_obj.__next__())

执行报错:

1
Traceback (most recent call last):
2
3
File "E:/python_script/day13/迭代器.py", line 9, in <module>
print(l1_obj.__next__())
StopIteration

多取了一个,就会报错,因为列表只有3个元素

 

总结:

仅含有__iter__方法的,就是可迭代对象
包含__iter__和__next__方法的,就是迭代器

 

二、生成器

生成器:生成器本质上是迭代器

1 l = [1,2,3]
2 l.__iter__() 

#生成器的产生方式:
1,生成器函数构造。
2,生成器推导式构造。
3,数据类型的转化。

1 def func1():
2     print(111)
3     print(222)
4     print(333)
5     return 666
6 print(func1())

执行输出:

111
222
333
666

将函数转换为生成器

1 def func1():
2     print(111)
3     print(222)
4     print(333)
5     yield 666
6 g = func1()
7 print(g)

执行输出:

<generator object func1 at 0x000001B4C369DE60>

第一:函数中只要有yield 那他就不是一个函数,而是一个生成器
第二:g称作生成器对象。

 

迭代器,使用__next__取值

1 def func1():
2     print(111)
3     print(222)
4     print(333)
5     yield 666
6 g = func1()
7 print(g.__next__())
8 print(g.__next__()) 

执行报错
一个__netxt__对应一个yield

对于列表而言,for循环是从开始
对于生成器而言,它是有指针的,__next__一次,指针向前一次。它不能从头开始。
必须依次执行才行

生成器和迭代器的区别
迭代器: 有内置方法
生成器: 开发者自定义

 

send()

 1 def generator():
 2     print(123)
 3     content = yield 1
 4     print('=======',content)
 5     print(456)
 6     yield
 7  
 8 g = generator()
 9 ret = g.__next__()
10 print('***',ret)
11 ret = g.send('hello')   #send的效果和next一样
12 print('***',ret)

执行输出:

123
*** 1
======= hello
456
*** None

 

send 获取下一个值的效果和next基本一致
只是在获取下一个值的时候,给上一yield的位置传递一个数据
使用send的注意事项

   第一次使用生成器的时候 是用next获取下一个值
   最后一个yield不能接受外部的值

 

next 和send 功能一样,都是执行一次
send可以给上一个yield赋值。

 

posted @ 2018-09-18 16:12  北三环的雪  阅读(105)  评论(0编辑  收藏  举报