我的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]

如果要生成[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 特点

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

猜你喜欢

转载自www.cnblogs.com/Sunzz/p/9150335.html