python基础十二 迭代器、生成器

1.迭代器

1.1 含义

一个一个取值

1.2 可迭代对象

#Python中规定,只要是具有__iter__()方法就是可迭代对象       
str.__iter__()                           
list.__iter__()                          
tuple.__iter__()                         
dict.__iter__()                          
set.__iter__()    

⚠️可迭代对象能够重复取值

1.3 迭代器使用示例

//使用示例1   将迭代器赋值给一个变量,这样就能重复取值了
可迭代对象能够重复取值                   
lst = [1,1,2]             

将可迭代对象转换成迭代器        
l = lst.__iter__()            
print(l)                  
    #结果:<list_iterator object at 0x7fc49811a0f0>,迭代器的内存空间地址        
print(l.__next__())      #结果:1
print(l.__next__())      #结果:1   
print(l.__next__())      #结果:2
print(1.__next__())        #结果:StopIteration 停止迭代,不能超过元素个数
⚠️有多少个元素就只能next多少次


//使用示例1        单独执行迭代器,这样每次只能取第一个值
lst = [1,1,2,4,5]                

⚠️以下两个lst.__iter__()迭代器内存地址,mac中显示的是一样,win本有的一样,有的不一样!!!
print(lst.__iter__())        #<list_iterator object at 0x7fd0a80110f0>
print(lst.__iter__())        #<list_iterator object at 0x7fd0a80110f0>
print(lst.__iter__().__next__())  #结果:1  #lst.__iter__() 是一个迭代器1
print(lst.__iter__().__next__())  #结果:1  #lst.__iter__() 是一个迭代器1
⚠️这里迭代器是多个

1.4 for循环本质

⚠️⚠️⚠️for循环就是一个迭代器
s = "hehe"
for i in s:
    print (i)
h
e
h
e 



s = "hehe"
s1 = s.__iter__()
while True:
    print (s1.__next__())

结果会报错如下:停止迭代         
StopIteration         



s = "hehe"
s1 = s.__iter__()
while True:
    try:     #尝试着运行一下缩进体中的内容,如果运行有问题用except接收一下
        print (s1.__next__())
    except StopIteration:
        break           
结果如下:
h
e
h
e

1.5 python3中迭代器用法

//python1和python2中迭代器共同用法
lst = ['a',1,2,4,5]
print (iter(lst))
print (iter(lst))
print (iter(lst).__next__())
print (iter(lst).__next__())

结果如下:
<list_iterator object at 0x7fe4e8071668>
<list_iterator object at 0x7fe4e8071668>
a
a


//python1中支持__iter__()方法
//python1中不支持 __next__()方法

2.生成器

2.1 生成器含义

控制循环迭代行为,一边循环一边计算的特殊程序

例如,创建一个包含100万元素的列表,不仅占空间。而且如果只访问前边几个元素,后续的元素空间就白白浪费了,生成器可以根据规则生成后续元素

2.2 生成器定义

1.基于函数实现的生成器 2.表达式实现生成器

2.3 生成器本质

生成器的本质就是一个迭代器

迭代器:文件句柄,通过数据转换,python自带提供

生成器:程序员自己实现

2.4 生成器使用示例

2.4.1 定义及创建生成器

#定义一个函数
def func():
    print (1)
    return 5
print (func())  
1
5

⚠️函数题中存在关键字yield就是定义一个生成器
#定义一个生成器
def func():
    print (1)
    yield 5
print (func())         #⚠️这一步才算是创建一个生成器对象
<generator object func at 0x7f8df8127d00>

2.4.2 语法及词法

⚠️代码执行的时候有多个对象在工作
语法检查
词法检查


//示例1
def func():
    print (foo)
返回结果为空

原因:
    函数没有被调用,因此不报错

//示例1
def func():
    if 2 > 1
结果:
    SyntaxError: invalid syntax

原因:
    首先进行语法检查,语法错误


//示例2
def func():
    foo()
func()
结果:
    报错,语法检查没有问题,但是词法检查有问题

2.4.3 生成器使用

2.4.3.1 生成器使用示例1
⚠️⚠️⚠️生成器最大特点:惰性机制
//示例1
def func():
    yield 1        #记录执行位置,当第一次next的时候记录,第二次next的时候就开始从下边取值
    yield 1
    yield 2

g = func()            #获取的是生成器的内存地址
print (next(g))    #取值 1
print (next(g))    #取值    1
print (next(g))    #取值    2
print (next(g))    #取值    会报错 StopIteration
2.4.3.2 生成器使用示例2
//示例1
def func():
    yield 1        #记录执行位置,当第一次next的时候记录,第二次next的时候就开始从下边取值
    yield 1
    yield 2

g = func()
g1 = func()
g1 = func()
print (g)
print (g1)
print (g1)
<generator object func at 0x7faa180b7d00>
<generator object func at 0x7faa180b7db0>
<generator object func at 0x7faa180b7e08>

print (next(func()))        #这是一个生成器1
print (next(func()))        #这是一个生成器1
print (next(func()))        #这是一个生成器2
1
1
1


⚠️⚠️⚠️yieldreturn部分功能很像
def func():
    yield
print(next(func()))
None                                #yeild后边不写内容返回的是None
2.4.3.3 生成器使用示例3
//示例2
def func():                                        #1
    def foo():                                #1
        print (1)                            #2
    yield foo                                    #4
g = func().__next__()                    #5
print (g)                    #结果 <function func.<locals>.foo at 0x7fdb08082400>
print (g())                #结果 1 None
print (type(g))        #结果 <class 'function'>

🐷示例2执行过程
第一步,定义一个函数func():  第1行
第二步,执行第5行的func(),创建一个生成器
第三步,执行第5行func().__next__(),进行去值,获取的是生成器的内存空间地址
第四步,执行第12行的foo函数,只是定义一个foo函数,没有实际调用
第五步,执行第4行的yield foo,yield foo获取的是foo函数的内存空间地址,并且返回给变量g  此时g就是foo函数的内存地址
第六步,print (g),返回的是foo的函数内存地址
第七步,print (g()),g() == foo(),返回1,函数体中默认返回None
第八步,print (type(g)),返回的是foo函数的类型
2.4.3.4 生成器使用示例4
//示例4
def func():
    yield 1,1,2,4,5
    print (112)
    yield 1111
    yield 666
g = func()
print (next(g))        #结果 (1, 1, 2, 4, 5)
print (next(g))        #结果 112 1111

2.5 时间 空间

2.5.1 空间换时间

//概念
例如,一个列表要产生50000个元素,一次性创建,这样就是用了空间换了时间
用一次性生成占用大量空间的元素换取快速读取时间

2.5.2 时间换空间

//概念
例如,还是一个列表创建50000个元素,这次不一次性创建,而是创建一个监控者,用一个元素由监控者取一个,这样就节省了大量内存空间,但是需要读取的时间变长

//代码示例
def func():
    for i in range(1,50001):
        yield i
g = func()
print (next(g))        #结果1
print (next(g))        #结果1

这样就是需要一个然后读取一个,节省了内存空间地址,但是需要消耗大量时间

2.6 yield from

yield from 逐个返回对象

//示例1 将元素整体返回
def func():
    yield [1,1,2,4,5]        #将元素整体返回
g = func()
print (next(g))
[1, 1, 2, 4, 5]

//示例1 将元素逐个返回
def func():
    yield from [1,1,2,4,5]
g = func()
print (next(g))
print (next(g))
print (next(g))
1
1
2


//示例2    多个yield,逐个返回一个yield的元素再返回下一个yielddef func():
    yield from [1,1,2]
    yield from ['a','b','c','d','e']
g = func()
print (next(g))
print (next(g))
print (next(g))
print (next(g))
1
1
2
a

#yield总结
yield 能返回多个,以元组的形式存储       
yield 能返回各种数据类型(Python的对象) 
yield 能够写多个并且都执行           
yield 能够记录执行位置             
yield 后边不写内容 默认返回None      
yield 都是将数据一次性返回

3.区分迭代器和生成器及迭代对象说明

#方法1
具有send()方法的就是一个生成器


#方法1
查看内存地址

//示例
lst = [1,1,2]
print (lst.__iter__())        #结果 <list_iterator object at 0x7fc568161668>

def func():
     yield 1
print (func())    #结果 <generator object func at 0x7fc55804fd00>


⚠️⚠️⚠️
生成器一定是一个迭代器,但是迭代器不一定是一个生成器


//迭代对象
具有__iter__()方法的就是一个可迭代对象

//迭代器:                              
具有__iter__() 和 __next__()方法就是一个迭代器

//生成器:                              
基于函数创建的生成器,函数体中必须存在yield

4.迭代器和生成器优缺点总结

#优点
节省空间

#缺点
1.不能直接使用元素
1.不能直观查看元素的个数
2.使用不灵活
4.稍微消耗时间
5.一次性执行,不能逆行执行
泡泡吐肥皂o © gitbook.pptfz.top 2021 all right reserved,powered by Gitbook文件修订时间: 秃笔南波湾!!!

results matching ""

    No results matching ""