Python全栈开发实战学习6

生成器&迭代器

列表生成式

把列表[0,1,2,3,4,5,6,7,8,9]中的每个元素加1

a = [i+1 for i in range(10)]
print(a)

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

这样的写法就叫做列表生成式

生成器

  • 生成器——迭代器
  • 生成器函数——本质上就是我们自己写的函数
  • 列表生成式

列表是可迭代的,但不是迭代器

l = [1,2,3,4,5,6]
for i in l:    # 生成了一个迭代器
   print(i)
   if i == 2:
       break
for i in l:      # 又生成了一个迭代器
   print(i)

结果
1
2
1
2
3
4
5
6

生成器的作用:当列表中的元素个数很多时,甚至大于内存容量,查看列表中元素,如果一次性将所有元素装入内存,显然不合适。这时可以用生成器来解决这一问题,生成器执行时一次装入部分元素到内存,且具有记忆功能,可以从停止的地方接着往下执行。

def func():
   for i in range(2000000):
       yield '衣服%s' % i

f = func()
f1 = func()
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f1.__next__())

结果
衣服0
衣服1
衣服2
衣服0

从上面的代码中我们可以看到,f 和 f1 是两个互不干扰的生成器。
yield 类似于 return ,返回一个生成器,是生成器函数中特有的
f.next()和f.iter()是对结果进行操作的内置函数

def func():    # 生成器函数
   for i in range(2000000):
       yield '衣服%s' % i

f = func()
count = 0
for i in f:    # 打印 衣服1-5
   print(i)
   count += 1
   if count>5:
       break

print(f.__next__())  # 打印 衣服6

for i in f:    # 打印 衣服7-11
   print(i)
   count += 1
   if count>10:
       break

结果
衣服0
衣服1
衣服2
衣服3
衣服4
衣服5
衣服6
衣服7
衣服8
衣服9
衣服10
衣服11

从以上代码中我们可以看出,生成器函数随用随停,再用的时候会从断点继续往下执行。

示例

def tail(filename):
   f = open(filename, encoding='utf8')  # 以读方式打开,不用刻意写mode='r'
   while True:  # 保持监听
       line = f.readline().strip() # readlines()生成列表,不太合适;read()可以但是开销大
       if line:
           yield line

g = tail('监听文件')
for i in g:
   if 'python' in i:
       print('****', i)

迭代器

可以直接作用于for循环的数据类型有:

  • 一类是:list、tuple、dict、set、str、f=open()、range()、enumerate
  • 另一类是:generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:iterable。
可以使用isinstance()判断一个对象是否是Iterable对象
而生成器不当可以作用于for循环,还可以被next()函数不断调用并返回下一个值,知道最后抛出StopIteration错误表示无法继续返回下一个值了。

  • 可以被next()函数调用并不断返回下一值的对象称为迭代器:Iterator对象

Iterable可迭代的 ——> _ iter_ #只要含有_iter_方法的都是可迭代的
[]._ iter_() 迭代器 ——> _ next_ #通过next可以从迭代器中一个一个取值

只要含有_iter_方法的都是可迭代的 ——Python可迭代协议
迭代器协议:只要同时含有_ iter_和_ next_方法的函数就是迭代器

做一个测试:

from collections.abc import Iterable
from collections.abc import Iterator

class A:
    def __iter__(self):pass
    def __next__(self):pass

a = A()
print(isinstance(a, Iterable))     # 判断是否可迭代
print(isinstance(a, Iterator))     # 判断是否是一个迭代器

结果
True
True

显然由因为class A中定义了iter和next方法,所以新创建的对象a是可迭代的,同时也是一个迭代器。
下面把两个方法分别注释一下,我们看一下结果

from collections.abc import Iterable
from collections.abc import Iterator

class A:
    def __iter__(self):pass
    #def __next__(self):pass

a = A()
print(isinstance(a, Iterable))
print(isinstance(a, Iterator))

结果:
True   # 是可迭代的
False  # 不是迭代器
from collections.abc import Iterable
from collections.abc import Iterator

class A:
    #def __iter__(self):pass
    def __next__(self):pass

a = A()
print(isinstance(a, Iterable))
print(isinstance(a, Iterator))

结果:
False	# 不可迭代
False   # 不是迭代器
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值