我的Python之旅第五天---迭代器和生成器
我的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)
结果为:
<str_iterator object at 0x00000234253C83C8>
<list_iterator object at 0x00000234253C89E8>
(2)第二种方法iter()
str1="abcdegggg"
list1=[1,3,4,5]
obj_str=iter(str1)
obj_list=iter(list1)
print(obj_str)
print(obj_list)
结果为:
<str_iterator object at 0x00000170FF5B8240>
<list_iterator object at 0x00000170FF5B83C8>
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
二 生成器
在Python中,使用了yield的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,等简单的理解生成器就是一个迭代器。在调用生成器的运行的过程中,每当遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值,并在下一次执行next()方法是从当前暂停的位置继续运行。
调用一个生成器,返回的是一个迭代器对象。
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 不能得到值
三 列表生成试
列表生成试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]
如果要生成[1×1,2×2…..10×10]怎么办,方法一是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 特点
列表生成试,直观可以看出,但是占内存