Python —— 生成器、迭代器

Python —— 生成器、迭代器

方法

判断一个对象是否是可迭代对象Iterable

1 from collections import Iterable
2 li = [1,2,3,4]
3 print(isinstance(li,Iterable))
4 # 结果为True,说明是可迭代对象
5 num = 1234
6 print(isinstance(num,Iterable))
7 # 结果为False,说明不是可迭代对象

判断一个对象是否是迭代器 Iterator

1 from collections import Iterator
2 li = [1,2,3,4]
3 print(isinstance(li,Iterator))
4 # 结果为False,说明不是迭代器
5 g_li = [1,2,3,4].__iter__()
6 print(isinstance(g_li,Iterator))
7 # 结果为True,说明是迭代器

三、可迭代对象:含有双下iter(__iter__)方法的对象就是可迭代对象

  迭代器:同时含有 __iter__ 和 _-next__ 方法的对象是迭代器

  生成器就是迭代器,只不过是pythoner自己开发的迭代器

查看数据类型可用的方法: dir():

1 li = [1,2,3]
2 print( dir(li) )
3 #运行结果 ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__',
'__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear',
'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

四、迭代器

  1、可迭代协议:只要包含了双下iter方法的数据类型就是可迭代的。迭代协议是数据类型与python解释器定下来的协议

    可迭代对象是不能取出数的,迭代器实现了从其中一个一个的取出数来

1 li = [1,2,3]
2 print(li.__iter__())  # __iter__方法将可迭代对象转换为迭代器

  2、迭代器协议:迭代器中有__next__ 和 __iter__ 方法

  3、从迭代器中取值:

1 g = [1,2,3].__iter__()
2 print(g.__next__())   # 每取完一个数,光标移动,下一次取数光标从该位置开始取下一个值
3 print(g.__next__())
4 print(g.__next__())

5 print(g.__next__())  # 当迭代器中数据取完时,程序报错,StopIteration(终止迭代)

   4、迭代器和可迭代对象的关系:

    # 迭代器包含可迭代对象

    # 迭代器 = 可迭代对象.__iter__()

  5、为什么要使用迭代器,迭代器的本质是什么?

    # 迭代器能够对python中的基本类型数据进行统一的遍历,不需要关心每一个值分别是什么

    # 可以节省内存 -- 惰性运算:列表会将所有的值放入内存。

  6、迭代器的种类:

    # 1、本身就是迭代器,如文件句柄:

    # 2、可迭代对象.__iter__()

异常处理

    迭代器中元素个数是有限的,当取值次数超过元素个数时,程序报错:StopIteration

    报错:

1 li = [1,2,3]
2 li_g = li.__iter__()
3 while True:
4     for i in range(100):
5         print(li_g.__next__())

# 运行结果:
 1
2
3
 Traceback (most recent call last):
  File "D:/oldboy/s7课上所有 - 老师版/day14/3迭代器.py", line 88, in <module>
   print(li_g.__next__())
 StopIteration

    解决办法如下:try - except

1 li = [1,2,3]
2 li_g = li.__iter__()
3 while True:
4     for i in range(100):
5         try:
6             print(li_g.__next__())
7         except StopIteration:
8             break
# 运行结果:
 1
2
3

生成器/两种

  1、生成器函数

    含有 yield 关键字的函数叫生成器函数,生成器函数执行时返回一个生成器

    ① 生成器的基本格式

      1、yield后不写内容,得到结果None

      2、不写yield,函数是普通函数。

      3、只有一个yield,作用同return,所以生成器函数至少要包括两个yield。

 1 def generator():
 2     print(111)
 3     yield 333
 4     print(222)
 5     yield 444
 6 
 7 g = generator()  # 直接调用生成器函数,会得到一个生成器 g ,print后得到的是生成器的地址
 8 print(g)
 9 for i in g:    # 每次循环,得到一个yield对应的值,光标移动到当前位置,下次循环从光标位置开始寻找下一个yield
10     print(i)
# 运行结果:
# <generator object generator at 0x000001B6DC96D048>
  111
  333
  222
  444

     ② 利用for循环实现 yield

     虽每循环一次,就有一个yield

1 def clothing():
2     for cloth in range(1,2001):
3         yield "已做完第 %s 件校服。"% cloth
4 
5 g = clothing()
6 for i in range(30):
7     print(g.__next__())
# 运行:
 已做完第 1 件校服
 已做完第 2 件校服
  ...
 已做完第 30 件校服

    ③ 监控文件的输入,并打印出输入内容

 1 import time
 2 def tail(filename):
 3     f = open(filename,encoding='utf-8')
 4     f.seek(0,2)   #将文件的光标移到最后
 5     while True:
 6         line = f.readline()
 7         if not line:
 8             time.sleep(0.1)
 9             continue
10         yield line
11 
12 tail_g = tail('demo')
13 for line in tail_g:
14     print(line,end='')

  2、生成器表达式

  3、yield from

1 def func():
2     for i in [1,2,3]:
3         yield i
4     for j in "ABCD":
5         yield j
6 
7 def func():
8    yield from [1,2,3]
9    yield from "ABCD"

 

 

posted @ 2017-09-04 18:53  乖巧Clare  阅读(114)  评论(0)    收藏  举报