一、迭代器

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

第二种:

  1. from collections import Iterable
  2. l = [1, 2, 3, 4]
  3. print(isinstance(l, Iterable))

执行输出:

True

  1. from collections import Iterable
  2. l = [1, 2, 3, 4]
  3. print(type(l))
  4. print(isinstance(l,list))

执行输出:

True

type只能判断是什么类型

isinstance判断方面更广,不仅能判断类型,还能判断是否可迭代

迭代器

可迭代对象转化成迭代器:可迭代对象.iter() —->迭代器

迭代器不仅含有iter,还含有next。遵循迭代器协议。

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

执行输出:

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

  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

从结果中,可以看出l1obj是同时含有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

print(l1obj._next())

StopIteration

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

使用for循环方式

  1. l1 = [1,2,3]
  2. l1_obj = l1.__iter__() # 转换为迭代器
  3. for i in l1_obj:
  4. print(i)

执行输出:

1

2

3

for循环的内部机制,就是用next方法执行的。为什么没有报错呢?它内部有异常处理机制

总结:

仅含有iter方法的,就是可迭代对象

包含iternext方法的,就是迭代器

判断迭代器的2种方法:

第1种:

  1. l1 = [1,2,3]
  2. l1_obj = l1.__iter__() # 转换为迭代器
  3. print('__iter__' in dir(l1_obj))

第2种:

  1. l1 = [1,2,3]
  2. l1_obj = l1.__iter__() # 转换为迭代器
  3. from collections import Iterator
  4. print(isinstance(l1_obj, Iterator))

返回True,就表示它是的

迭代器的好处:

1,节省内存空间。

2,满足惰性机制。

3,不能反复取值,不可逆。

不可逆,表示,已经取过的值,不能再次取,它只能取下一个。

for处理机制

  1. l2 = [1, 2, 3, 4, 5, 6, 7, 8]
  2. for i in l2:
  3. print(i)

1,将可迭代对象转化成迭代器

2,内部使用next方法取值

3,运用了异常处理去处理报错。

迭代器最大的好处,就是节省内存

好的程序员,会在内存优化方面考虑,比如迭代器。

使用while循环,指定用next方法遍历列表

  1. l2 = [1, 2, 3, 4, 5, 6, 7, 8]
  2. l2_obj = l2.__iter__() #1.将可迭代对象转化成迭代器
  3. while True:
  4. try:
  5. i = l2_obj.__next__() #内部使用__next__方法取值
  6. print(i)
  7. except Exception: #运用了异常处理去处理报错
  8. break

try里面的代码,出现报错,不会提示红色文字

Exception 可以接收所有报错,表示报错的时候,该怎么处理,这里直接使用breck跳出循环

面试题:

使用whlie循环去遍历一个有限对象

直接使用上述代码即可。

二、生成器

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

  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)

执行输出:

第一:函数中只要有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

比如生产10000套服装

一个厂商直接生产出10000套了

  1. def func1():
  2. for i in range(1,10001):
  3. print('ARMAIN服装%d套' % i)
  4. func1()

执行输出:

ARMAIN服装9998套

ARMAIN服装9999套

ARMAIN服装10000套

第二个厂商,先生产出50套,给老板看

  1. def func1():
  2. for i in range(1,10001):
  3. yield 'ARMAIN服装%d套' % i
  4. g = func1()
  5. for i in range(1,51):
  6. print(g.__next__())

执行输出:

ARMAIN服装48套

ARMAIN服装49套

ARMAIN服装50套

最终老板只要200套

先50套,再150套

  1. def func1():
  2. for i in range(1,10001):
  3. yield 'ARMAIN服装%d套' % i
  4. g = func1()
  5. for i in range(1,51):
  6. print(g.__next__())
  7. #再执行150次,注意,它是从51开始的
  8. for j in range(150):
  9. print(g.__next__())

之前生产10000套的….

对于列表而言,for循环是从开始

对于生成器而言,它是有指针的,next一次,指针向前一次。它不能从头开始。

必须依次执行才行

生成器和迭代器的区别

迭代器: 有内置方法

生成器: 开发者自定义

send

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

执行输出:

123

* 1

======= hello

456

* None

send 获取下一个值的效果和next基本一致

只是在获取下一个值的时候,给上一yield的位置传递一个数据

使用send的注意事项

第一次使用生成器的时候 是用next获取下一个值

最后一个yield不能接受外部的值

next 和send 功能一样,都是执行一次

send可以给上一个yield赋值。

明日默写内容:

1.什么是可迭代对象,什么是迭代器

答:

内部含有iter方法的对象就叫做可迭代对象

内部必须有iter方法和next方法的对象,叫做迭代器

2.可迭代对象如何转化成迭代器

答:

转化成迭代器:可迭代对象.iter() —->迭代器

例如

  1. l1 = [1,2,3]
  2. l1_obj = l1.__iter__()

3.迭代器如何取值

答:

迭代器使用next()方法

4.什么是生成器?如何写一个生成器?生成器怎么取值?

答:

生成器,即生成一个容器。在Python中,一边循环,一边计算的机制,称为生成器。

生成器示例

  1. def fun1():
  2. yield 1

生成器使用next()方法取值,或者for循环