我的Python之旅第五天---迭代器和生成器

时间:2023-03-08 21:48:21
我的Python之旅第五天---迭代器和生成器

h3,#nv_portal .vw .d .h3 {display: block; font-weight: 500; background-image: linear-gradient(to right bottom, #00BCD4, #3F51B5);background-color: #3F51B5;color: #FFF; font-size: 1.8em; line-height: 2.0em; margin: 16px 10px 16px 0; padding: 12px 15px;letter-spacing:4px; border-left: solid #333 15px; text-shadow: 1px 1px 1px #666;box-shadow: 1px 1px 2px #666;}

一 迭代器

迭代器是Python最强大的功能之一,是访问集合元素的一种方式

迭代器是一种可以记住遍历的位置的对象。

##1迭代器的特点:
(1)节省内存
比如展现一个上亿元素的列表并计算,sum([i*i for i in range(1000000000)])
内存小的机器肯定要宕机
(2)惰性机制
调用一次__next__方法,执行一次
(3)单向执行,不可逆
既就是迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完后结束。只能往前不能后退
##2 判断对象是不是可迭代对象
(1)常见的课迭代对象
包含字符串str、列表list、元组tuple、字典dict、集合set、range以及文件句柄
(2)第一种判断方法__iter__
```
str1="abcdegggg"
list1=[1,3,4,5]
print('__iter__' in dir(str1))
print('__iter__' in dir(list1))
结果为:
True
True
```
(2)第二种判断方法 isinstance('abc',Iterable)
```
str1="abcdegggg"
list1=[1,3,4,5]
from collections import Iterable
print(isinstance(str1,Iterable))
print(isinstance(list1,Iterable))
print(isinstance(123,Iterable))
结果为:
True
True
False
```
##3创建迭代器的方法
将可迭代对象转化为迭代器
(1)第一种方法__iter__()
```
str1="abcdegggg"
list1=[1,3,4,5]
obj_str=str1.__iter__()
obj_list=list1.__iter__()
print(obj_str)
print(obj_list)
结果为:

```
(2)第二种方法iter()
```
str1="abcdegggg"
list1=[1,3,4,5]
obj_str=iter(str1)
obj_list=iter(list1)
print(obj_str)
print(obj_list)
结果为:

```
##4 判断对象是不是迭代器
(1)内部含有__iter__ 且含有__next__方法的对象就是迭代器,遵循迭代器协议
```
str1="abcdegggg"
list1=[1,3,4,5]
obj_str=str1.__iter__()
obj_list=list1.__iter__()

print('iter' in dir(str1))

print('next' in dir(str1))

print('iter' in dir(obj_str))

print('next' in dir(obj_str))

结果为:

True

False

True

True

可以看到,str1虽然是可迭代对象,但是内部不含有__next__方法,所以不是迭代器

(2)isinstance(obj_list,Iterable)

from collections import Iterable

list1=[1,3,4,5]

obj_str=str1.iter()

obj_list=list1.iter()

print(isinstance(list1,Iterable))

print(isinstance(obj_list,Iterable))

print(isinstance(124,Iterable))

结果为:

True

True

False

<h3>二 生成器</h3>

<blockquote background-color:yellow;>
<p>在Python中,使用了yield的函数被称为生成器(generator)。<br>
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,等简单的理解生成器就是一个迭代器。在调用生成器的运行的过程中,每当遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值,并在下一次执行next()方法是从当前暂停的位置继续运行。<br>
调用一个生成器,返回的是一个迭代器对象。
</p>
</blockquote>
##1创建一个简单的生成器

def func1():

print(1111)

yield 1

print(2222)

yield 2

print(3333)

yield 3

print(4444)

gener_obj=func1()

print(gener_obj.next())

print(gener_obj.next())

print(gener_obj.next())

结果为:

1111

1

2222

2

3333

3

上边示例中gener_obj=func1()为生成器对象
__next__() 和 yield 必须一一对应
每调用一次__next__()执行一个yield
如果__next__()多于yield则会报错
##2 生成器小试牛刀
(1)

def cloth():

for i in range(1,1000):

yield '衣服%s'%i

ger_obj=cloth()

for i in range(3):

print(ger_obj.next())

结果为:

衣服1

衣服2

衣服3

(2)接下来再次取值时,它会从上次停的地方继续运行

def cloth():

for i in range(1,1000):

yield '衣服%s'%i

ger_obj=cloth()

for i in range(3):

print(ger_obj.next())

for i in range(5):

print(ger_obj.next())

结果为:

衣服1

衣服2

衣服3

衣服4

衣服5

衣服6

衣服7

衣服8

可以看到,它并不会重复打印1-3
##3 send和next的区别
send 和next 都是对生成器取值
send 会给上一个yield 发送一个值。
send 不能用在第一次取值。
最后一个yield 不能得到值 <h3>三 列表生成试</h3>
列表生成试List Comprehensions,是Python内置的非常简单却强大的可以用了创建list的生成试。
##1为何要使用列表生成试
举个例子,要生成list[1,2,3,4,5,6,7]可以用list(range(1,8)):

list(range(1,8))

[1, 2, 3, 4, 5, 6, 7]

如果要生成[1x1,2x2…..10x10]怎么办,方法一是for循环

for i in range(1,11):

list1.append(i*i)

list1

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

循环太繁琐了,二使用列表生成试一行语句就可以搞定上边的list

[x*x for x in range(1,11)]

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

##2 列表生成试的一般格式
(1)遍历模式
[变量(加工后的变量) for 变量 in iterable] 遍历模式
如:list = [i for i in range(1,11)]

list = [i for i in range(1,11)]

list

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

(2)筛选模式
[变量(加工后的变量) for 变量 in iterable if 条件] 筛选模式
如:list2 = [i for i in range(1,31) if i % 3 == 0]

list2 = [i for i in range(1,31) if i % 3 == 0]

list2

[3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

##3 特点
列表生成试,直观可以看出,但是占内存