python基础篇_005_迭代器和生成器

Python迭代器和生成器

1.迭代器

迭代:可以将某个数据集内的数据“一个挨着一个的取出来”

for i in range(1, 10, 2):  # in 后面的对象必须是一个可迭代的
print(i) # 从可迭代对象中将元素一个一个取出
"""
判断是否可迭代
"""
from collections import Iterable str1 = 'adc'
l = [1, 2, 3, 4]
t = (1, 2, 3, 4)
d = {1: 2, 3: 4}
s = {1, 2, 3, 4}
print(isinstance(str1, Iterable))
print(isinstance(l, Iterable))
print(isinstance(t, Iterable))
print(isinstance(d, Iterable))
print(isinstance(s, Iterable)) # True int1 = 1234
print(isinstance(int1, Iterable)) # False

2.可迭代协议

可以被迭代要满足的要求就叫做可迭代协议。内部实现了__iter__方法。

print(dir(str))  # 可迭代,内部要有一个__iter__()方法
print(str1.__iter__())
#['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
#<str_iterator object at 0x0000000000A6DB38>
str_iterator iterator 就是迭代器
str1 = 'abc'
dir(str1) # 列出所有字符串实现的方法
set1 = set(dir(str1))
set2 = set(dir(str1.__iter__()))
print(set2 - set1)
# {'__length_hint__', '__next__', '__setstate__'}

迭代器多了三个方法

"""迭代器中的方法作用"""
str1 = 'abc'
# 获取迭代器
iter_1 = str1.__iter__()
# 获取迭代器中元素的长度
print(iter_1.__length_hint__()) # 3
# 根据索引值指定从哪里开始迭代
print(iter_1.__setstate__(1)) # None
# 一个一个的取值
print(iter_1.__next__()) # b for 循环内部调用 实现一个一个取值

自己实现迭代取数:

str1 = 'abc'
# 获取迭代器
iter1 = str1.__iter__() # 循环取出
while 1 :
a = iter1.__next__()
print(a)
# a
# b
# c
#
# Traceback (most recent call last):
# File "E:/Python/d01/函数.py", line 8, in <module>
# a = iter1.__next__()
# StopIteration

异常机制处理异常:

str1 = 'abc'
# 获取迭代器
iter1 = str1.__iter__() # 循环取出
while 1:
try:
a = iter1.__next__()
print(a)
except StopIteration:
break
# a
# b
# c

3.生成器

实现迭代器功能的东西就是生成器

Python中提供的生成器:

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行

2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

生成器Generator:

  本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

  特点:惰性运算,开发者自定义

生成器函数

1.生成器函数:一个包含yield关键字的函数就是一个生成器函数。
2.yield与reduce区别:
yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,
而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
def genrator_f1():
a = 1
print('a变量')
yield a
b = 2
print('b变量')
yield b g1 = genrator_f1() # g1获取的是生成器
print(g1.__next__())
print(g1.__next__())
print(g1.__next__()) # a变量
#
# b变量
#
# Traceback (most recent call last):
# File "E:/Python/d01/test.py", line 14, in <module>
# print(g1.__next__())
# StopIteration

生成器的优点:不会在内存中瞬间生成很多数据

def produce():
for i in range(10):
yield "生产序列号:%d" % i # 获取生成器
pro_g = produce()
print(pro_g.__next__()) # 一个一个获取
print(pro_g.__next__())
print(pro_g.__next__()) num = 0 # 批量获取
for i in pro_g:
print(i)
num += 1
if num == 5:
break
# 生产序列号:0
# 生产序列号:1
# 生产序列号:2
# 生产序列号:3
# 生产序列号:4
# 生产序列号:5
# 生产序列号:6
# 生产序列号:7

实现日志实时监控: Linux tail -f

import time

def tail(filename):
with open(filename,mode='r',encoding='utf-8') as f:
f.seek(0, 2) # 从文件末尾算起
while True:
line = f.readline() # 读取文件中新的文本行
if not line:
time.sleep(1)
continue
yield line tail_g = tail('C:\\Users\\18047463\\Desktop\\test.txt')
for line in tail_g:
print(line.strip())

实时计算平均数:

def averager():
total = 0.0
count = 0
average = None
while 1:
term = yield average
total += term
count += 1
average = total / count g_avg = averager()
g_avg.__next__() # 初始化
while 1:
num = input(">>>")
if num == 'q':
break
print(g_avg.send(int(num)))

初始化使用装饰器:

from functools import wraps

def init(func):
@wraps(func)
def inner(*args, **kwargs):
g = func(*args, **kwargs)
g.__next__()
return g return inner @init
def averager():
total = 0.0
count = 0
average = None
while 1:
term = yield average
total += term
count += 1
average = total / count g_avg = averager()
while 1:
num = input(">>>")
if num == 'q':
break
print(g_avg.send(int(num)))
def gen1():
for c in 'AB':
yield c
for i in range(3):
yield i print(list(gen1())) def gen2():
yield from 'AB'
yield from range(3) print(list(gen2()))

列表推导式和生成器表达式

egg_list=['鸡蛋%s' %i for i in range(10)]  #列表解析
print(egg_list)
# ['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']
laomuji=('鸡蛋%s' %i for i in range(10)) #生成器表达式 相比列表解析,更加节省内存
print(laomuji) # <generator object <genexpr> at 0x00000000013F8780>
print(next(laomuji)) #next本质就是调用__next__
print(laomuji.__next__())
print(next(laomuji))
上一篇:input上传图片预览


下一篇:Windows10下安装Docker的步骤