【Python3之迭代器,生成器】

一、可迭代对象和迭代器

1.迭代的概念

上一次输出的结果为下一次输入的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值

注:循环不是迭代

while True: #只满足重复,因而不是迭代
     print(‘====>‘)

2.可迭代的对象

内置__iter__方法的,都是可迭代的对象。

list是可迭代对象,dict是可迭代对象,set也是可迭代对象。

[1,2].__iter__()
‘hello‘.__iter__()
(1,2).__iter__()

{‘a‘:1,‘b‘:2}.__iter__()
{1,2,3}.__iter__()

例如:

x = [1, 2, 3]
y = iter(x)
z = iter(x)
print(next(y))
print(next(y))
print(next(z))
print(type(x))
print(type(y))

输出

1
2
1
<class ‘list‘>
<class ‘list_iterator‘>

如下图所示

这里x是一个可迭代对象,yz是两个独立的迭代器,迭代器内部持有一个状态,该状态用于记录当前迭代所在的位置,以方便下次迭代的时候获取正确的元素。

迭代器有一种具体的迭代器类型,比如list_iteratorset_iterator。可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。

3.迭代器

  • 1.为什么要有迭代器?

对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式。

  • 2.迭代器定义:

迭代器:可迭代对象执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法

它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter____next__()方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常

  • 3.迭代器的实现

例:

i=[1,2,3].__iter__()  

print(i)    #迭代器

print(i.__next__())
print(i.__next__())
print(i.__next__())
#print(i.__next__()) #抛出异常:StopIteration

输出

<list_iterator object at 0x1019c3eb8>
1
2
3

每次调用next()方法的时候做两件事:

  1. 为下一次调用next()方法修改状态
  2. 为当前这次调用生成返回结果

迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。

  • 4.如何判断迭代器对象和可迭代对象

from collections import Iterable,Iterator
‘abc‘.__iter__()
().__iter__()
[].__iter__()
{‘a‘:1}.__iter__()
{1,2}.__iter__()

f=open(‘a.txt‘,‘w‘)
f.__iter__()
#判断是否为可迭代对象,以下都是
print(isinstance(‘abc‘,Iterable))
print(isinstance([],Iterable))
print(isinstance((),Iterable))
print(isinstance({‘a‘:1},Iterable))
print(isinstance({1,2},Iterable))
print(isinstance(f,Iterable))
#判断是否为迭代器,只有文件是
print(isinstance(‘abc‘,Iterator))
print(isinstance([],Iterator))
print(isinstance((),Iterator))
print(isinstance({‘a‘:1},Iterator))
print(isinstance({1,2},Iterator))
print(isinstance(f,Iterator))

输出

True
True
True
True
True
True
False
False
False
False
False
True

可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象

迭代器:有__iter____next__()方法

注:对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身

  • 5.迭代器的优点和缺点

优点:
1.提供了一种不依赖下标的迭代方式
2.就跌迭代器本身来说,更节省内存

缺点:
1. 无法获取迭代器对象的长度
2. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退

二、生成器

1.定义

生成器(generator)是一个特殊的迭代器,它的实现更简单优雅,yield是生成器实现__next__()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。

也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。

yield的功能:
1.相当于为函数封装好__iter__和__next__
2.return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行

例:

def counter(n):
    print(‘start...‘)
    i=0
    while i < n:
        yield i
        i+=1
    print(‘end...‘)

g=counter(5)
print(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# print(next(g))   #会报错

输出

start...
0
1
2
3
4

 

2.生成器函数

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

普通函数return返回

def lay_eggs(num):
    egg_list=[]
    for egg in range(num):
        egg_list.append(‘蛋%s‘ %egg)
    return egg_list

yikuangdan=lay_eggs(10) #我们拿到的是蛋
print(yikuangdan)

输出

[‘蛋0‘, ‘蛋1‘, ‘蛋2‘, ‘蛋3‘, ‘蛋4‘, ‘蛋5‘, ‘蛋6‘, ‘蛋7‘, ‘蛋8‘, ‘蛋9‘]

迭代器函数

def lay_eggs(num):
    for egg in range(num):
        res=‘蛋%s‘ %egg
        yield res       #生成器关键语法
        print(‘下完一个蛋‘)

laomuji=lay_eggs(10) #我们拿到的是一只母鸡
print(laomuji)
print(laomuji.__next__())       #迭代  蛋0
print(laomuji.__next__())     #蛋1
print(laomuji.__next__())       #蛋2
egg_l=list(laomuji)
print(egg_l)

输出

蛋0
下完一个蛋
蛋1
下完一个蛋
蛋2
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
[‘蛋3‘, ‘蛋4‘, ‘蛋5‘, ‘蛋6‘, ‘蛋7‘, ‘蛋8‘, ‘蛋9‘]

3.生成器表达式

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

    #g.send(‘food1‘),先把food1传给yield,由yield赋值给food,然后返回给food_list,然后再往下执行,直到再次碰到yield,然后把yield后的返回值返回给food_list

注意:开始生成器不能send非空值

def eater(name):        #协程函数
    print(‘%s ready to eat‘ %name)
    food_list=[]
    while True:
        food=yield food_list           #装饰器表达式
        food_list.append(food)
        print(‘%s start to eat %s‘ %(name,food))

g=eater(‘hexin‘)
print(g)        #生成器
print(g.send(‘food1‘))  #传值

输出

Traceback (most recent call last):
<generator object eater at 0x1049030f8>    #生成器对象
  File "/Users/hexin/PycharmProjects/py3/day5/2.py", line 71, in <module>
    print(g.send(‘food1‘))
TypeError: can‘t send non-None value to a just-started generator    #开始生成器不能send非空值
  • 初始化后

def eater(name):        #协程函数
    print(‘%s ready to eat‘ %name)
    food_list=[]
    while True:
        food=yield food_list           #装饰器表达式
        food_list.append(food)
        print(‘%s start to eat %s‘ %(name,food))

g=eater(‘hexin‘)
print(g)        #生成器
next(g) #等同于 g.send(None),初始化

print(g.send(‘food1‘))

输出

<generator object eater at 0x107cde258>
hexin ready to eat
hexin start to eat food1
[‘food1‘]
  • 为了防止忘记初始化,可利用装饰器进行初始化,如下

def deco(func):     #初始化函数
    def wrapper(*args,**kwargs):
        res=func(*args,**kwargs)
        next(res)          #等同于 g.send(None),初始化
        return res
    return wrapper

@deco       #用初始化函数装饰器,调用初始化函数
def eater(name):        #协程函数
    print(‘%s ready to eat‘ %name)
    food_list=[]
    while True:
        food=yield food_list           #装饰器表达式
        food_list.append(food)
        print(‘%s start to eat %s‘ %(name,food))

g=eater(‘hexin‘)
# print(g)        #生成器
# next(g) #等同于 g.send(None),初始化

print(g.send(‘food1‘))
print(g.send(‘food2‘))
print(g.send(‘food3‘))

输出

hexin ready to eat
hexin start to eat food1
[‘food1‘]
hexin start to eat food2
[‘food1‘, ‘food2‘]
hexin start to eat food3
[‘food1‘, ‘food2‘, ‘food3‘]

时间: 2024-10-10 22:05:34

【Python3之迭代器,生成器】的相关文章

python3.5-day5_迭代器_生成器_装饰器_模块

笔者QQ 360212316 迭代器&生成器 生成器: 一个函数调用返回一个迭代器,那这个函数叫做生成器,如果函数中包含yield语法,那么这个函数就会变成生成器 生成器的特点: 1.生成器必须从前往后一次访问,不能跳着取 2.生成器只记录访问的数据,其他数据释放 3.生成器的作用就是预想可能用到那么多的数据 生成器的两种方式: 方式一: data = (x * 2 for x in range(5)) # 获取结果的两种方式 print(data.__next__()) print(next(

python_day04 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式

本节课重要知识点内容如下: 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式 1.函数嵌套 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数 def bar(): print('from nbar')def foo(): print('from foo') bar()foo()def max2(x,y): if x > y: return x else: return ydef max4(a,

Day4 - 迭代器&amp;生成器、装饰器、Json &amp; pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青

函数嵌套 ,名称空间与作用域 ,闭包函数 ,装饰器 ,迭代器, 生成器 三元表达式,列表解析,生成器表达式 递归与二分法, 内置函数

函数嵌套名称空间与作用域闭包函数装饰器迭代器生成器三元表达式,列表解析,生成器表达式递归与二分法内置函数--------------------------------------------函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数def max(x,y): if x>y: return x else: return ydef max1(a,b,c,d): res=max(a,b) res2=max(res,c) res3=ma

[python]--迭代器,生成器补充

在python中,list,string,dict都是可迭代对象,可以通过for语句遍历. 迭代器 迭代器对象要求支持迭代器协议的对象,在python中,支持迭代器协议就算实现对象的__iter__()和next()方法.其中__iter__()方法返回迭代器对象本身; next()方法返回容器的下一个元素,在结尾时引发StopIteration异常 __iter__()和next()方法 这两个方法是迭代器最基本的方法,一个用来获得迭代器对象,一个用来获取容器中的下一个元素. 对于可迭代对象,

Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化

本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########## def orter(func):    #定义装饰器     de

day4装饰器-迭代器&amp;&amp;生成器

一.装饰器 定义:本质是函数,(装饰其他函数)就是为其它函数添加附加功能 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器知识储备: 1.函数及“变量” 2.高阶函数 a.把一个函数名当做实参传给另一个函数(在不修改被装饰器函数源代码的情况下为其添加新功能) b.返回值中包含函数名 3.嵌套函数 高阶函数+嵌套函数 = 装饰器 延迟3秒 import time def test1(): time.sleep(3) print('in the test1')

函数---迭代器&amp;生成器&amp;列表解析&amp;三元表达式

可迭代对象:obj.__iter__ 迭代器:iter1=obj.__iter() 1iter1.__next__ 2iter2.__next__ 迭代器: 优点:不依赖索引 惰性计算,节省内存 缺点: 不如按照索引的取值方便 一次性,只能往后取,不能回退 迭代器的应用: 提供了一种不依赖索引的统一的迭代方法 惰性计算,比如取文件的每一行 判断可是否是可迭代对象和迭代器 from collections import Iterable, Iterator # 导入模块功能 isinstance(

Python装饰器、迭代器&amp;生成器、re正则表达式、字符串格式化

Python装饰器.迭代器&生成器.re正则表达式.字符串格式化 本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########

Python 迭代器&amp;生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发

本节大纲 迭代器&生成器 装饰器  基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实的计算器所得出的结果一致 迭代器&