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

一 迭代器

迭代器是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 特点
列表生成试,直观可以看出,但是占内存
posted @ 2018-06-07 18:31  Sunzz  阅读(196)  评论(0编辑  收藏  举报