迭代器和生成器

本文深入探讨了Python中的迭代器和生成器。迭代器是不能获取元素个数且取出后不可放回的序列,通过`next()`或遍历获取元素。生成器与迭代器相似,但通过`yield`关键字实现,按需生成数据,节省内存。通过分析`func3`和`func4`展示了生成器的生成数据原理。最后,强调了生成器在处理大量数据时的内存效率优势,例如在读取CSV文件时。
摘要由CSDN通过智能技术生成

今日总结

一、迭代器

1. 什么是迭代器(iter)

是序列

迭代器作为序列无法获取元素的个数,打印迭代器的时候也无法查看所有的元素

如果要获取元素的值必须将元素从迭代器中取出来,而且某个元素如果取出来了就无法再放回迭代器中(取一个少一个)

2. 创建迭代器

  • 将其他序列转化成迭代器 - 所有序列都可以转换成迭代器
  • 创建生成器
iter1 = iter('abc')
print(iter1)        # <str_iterator object at 0x00000000025178B0>
# print(len(iter1))   # 报错!TypeError: object of type 'str_iterator' has no len()

iter2 = iter([100, 'abc', True, [1, 2]])
print(iter2)            # <list_iterator object at 0x0000000001E26FD0>

iter3 = iter({10, 20, 30})
print(iter3)            # <set_iterator object at 0x000000000256B040>

3. 获取元素

不管以什么样的方式获取到了迭代器的元素,那么这个元素就会从迭代器中消失

  1. next(迭代器) - 返回指定迭代器最前面的元素

  2. 遍历

iter4 = iter('python')
print(next(iter4))      # p
print(next(iter4))      # y
print(next(iter4))      # t
print(next(iter4))      # h
print(next(iter4))      # o
print(next(iter4))      # n
# print(next(iter4))      # 取一个空的迭代器会报错!StopIteration

iter5 = iter([10, 20, 'abc', True])
for x in iter5:
    print('x', x)

# print(next(iter5))      # 报错!StopIteration

iter6 = iter('abc')
list1 = list(iter6)
print(list1)
# print(next(iter6))      #报错!StopIteration

二、生成器

1. 什么是生成器

是序列

获取元素的方式和迭代器一样。一个数据只能取一次,取一个少一个,无法查看到所有数据

2. 怎么创建生成器

调用带有yield关键字的函数就可以得到一个生成对象

# 调用没有yield的函数:会执行函数体并且获取函数返回值
def func1():
    print('========')
    print('++++++++')

    
result = func1()
print(result)
print('-----------------------')
# 调用带有yield关键字的函数:不会执行函数体,返回的数据是一个生成器对象


def func2():
    print('========')
    print('++++++++')
    if False:
        yield
    return 100


result = func2()
print(result)       # <generator object func2 at 0x00000000020562E0>
print(list(result))     # [] -> 生成器result产生数据个数是0

3. 确定生成器产生数据的能力(包括产生数据的个数和值)

确定个数:执行完生成器对应的函数,会遇到几次yield,这个生成器就会产生多少个数据

def func3():
    yield 100
    yield 'abc'
    yield False
    # for _ in range(3):
    #     yield



g1 = func3()
# next(g1)
# next(g1)
# next(g1)
# next(g1)        # 报错!StopIteration

print(list(g1))     # [100, 'abc', False]

4. 生成器产生数据的原理

在获取数据的时候才去执行函数体,而且每次执行到yield就停下来,将yield后面值作为获取到的数据,同时记录结束位置,下一次获取元素接着上次结束的位置往后执行

def func4():
    print('开始')
    yield 10
    print('-------')
    yield 100
    print('+++++++')
    yield 1000
    print('结束')


g2 = func4()
# print('result1:', next(g2))
# print('result2:', next(g2))
# print('result2:', next(g2))
# print('result2:', next(g2))     # 会打印完'结束'后报错!StopIteration


def func5():
    print('hello')
    yield 11
    print('world')
    yield 22


g3 = func5()


next(g2)    # 开始
next(g3)    # hello
next(g2)    # -------
next(g3)    # world

# 练习:创建一个学号生成器,能产生指定范围的学号,学号的格式是:XXXxxx
# create_id(前缀, 长度)  ->  前缀是java, 长度是3  —> java001 ~ java999
# -> python2102, 长度是4  -> python21020001 ~ python21029999


def create_id(pre: str, length: int):
    for x in range(1, 10**length):
        yield f'{pre}{x:0>{length}}'


c1 = create_id('py', 4)
for x in c1:
    print(x)

四、生成器的优点

只读指令的数据,不占用运行内存,效率高

import csv

# 非生成器写法,需要遍历整个文件
def read_file1():
    with open('abc.csv', encoding='utf-8', newline='') as f:
        reader = csv.reader(f)
        result = []
        for x in reader:
            result.append(x)
        return result


# s = read_file1()
# print(s)


# 生成器写法,只读指令数据,无需遍历整个文件
def read_file2():
    with open('abc.csv', encoding='utf-8', newline='') as f:
        reader = csv.reader(f)
        # result = []
        for x in reader:
            yield x
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值