首页 > 编程语言 >18.Python基础篇-迭代器、生成器

18.Python基础篇-迭代器、生成器

时间:2024-10-18 21:48:11浏览次数:1  
标签:__ 函数 迭代 Python 18 生成器 next print

函数进阶-迭代器

 双下方法:

很少直接调用,一般情况下,都是通过其他语法触发的(Python解释器调用的方法)

可迭代协议 与 迭代器协议

可迭代的iterable与迭代器iter

可迭代协议:含有__iter__方法的都是可迭代的。

  可迭代的,一定可以被for循环。只要含有__iter__()方法能被for循环。

迭代器协议:含有__iter__方法和__next__方法的。

  迭代器一定可迭代。

可迭代的通过iter()方法就能得到一个迭代器。

迭代器的特点:

1.惰性计算:迭代器只在需要时生成数据,适合处理大数据集,减少内存占用。

2.随着循环每次在内存中生成一个值,而不是全部。每次调用next时返回一个值,也不是全部。

list1 = [1, 2, 3]

# 只有__iter__方法,没有__next__方法,说明列表是可迭代的
print('__iter__' in list1.__dir__())
print('__next__' in list1.__dir__())
# 输出结果
# True
# False


# 通过iter()方法将列表转换为迭代器。并验证是否存在__iter__方法与__next__方法。
list1_iterator = iter(list1)  # 调用iter方法返回当前可迭代对象的迭代器
print('__iter__' in list1_iterator.__dir__())
print('__next__' in list1_iterator.__dir__())
# 输出结果:
# True
# True

# 一个类中只要有iter方法就会认为是可迭代的,如果既有iter方法还有next方法,就会认为是迭代器
from collections import Iterator
from collections import Iterable
class A:
    def __iter__(self):
        pass
    def __next__(self):
        pass
a = A()
print(isinstance(a, Iterator))  # 判断是否是迭代器
print(isinstance(a, Iterable))  # 判断是否是可迭代的
# 输出结果:
# True
# True

# 迭代器中的__next__()方法
# __next__():以0为起点,获取迭代器中的下一个值
print(list1_iterator.__next__())  # list1_iterator中的第一个值
print(list1_iterator.__next__())  # list1_iterator中的第二个值
# 输出结果
# 1
# 2

# 迭代器中的__iter__()方法
iterator = list1.__iter__()  # 返回一个当前可迭代对象的迭代器
print(iterator)
# 输出结果:
# <list_iterator object at 0x00000271EBB2B970>

# 迭代器能节省内存的演示
print(range(1, 100000000000))  # 很快生成。因为range是一个迭代器,一个一个的返值
print(list(range(1, 100000000000)))  # 会报错MemoryError,电脑内存不够容纳这么大的列表。因为list不是迭代器,会一次生成全部数据。

函数进阶-生成器

生成器的本质,就是自己写的迭代器。一次返回一个值,而不是一次性生成所有的值。生成器通过使用 yield 关键字定义。(有yield的函数就是生成器函数)

生成器的两种形式:1.生成器函数。2,生成器表达式

生成器函数

生成器函数的定义:含有yield关键字的函数就是生成器函数;

生成器函数的特点:

1.调用函数时不会执行函数内部代码,而是返回一个生成器内存地址。

2.每次调用next()方法的时候会取到一个值。

3.直到取完最后一个,再执行next时会报错。

yield关键词

yield与return不能共用。与 return 不同,yield 不会终止函数的执行,而是暂停函数的执行,并返回一个值给调用者。函数在下次调用时会从上次暂停的地方继续执行。

def simple_generator():
    yield 1
    yield 2
    yield 3

gen = simple_generator()
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 2
print(next(gen))  # 输出: 3
# print(next(gen))  # 抛出 StopIteration 异常

 

生成器函数代码演示:

def generator():
    print('生成器函数中打印的数据1')
    yield 1
    print('生成器函数中打印的数据2')
    yield 2
    print('生成器函数中打印的数据3')
    yield 3

g = generator()  # 返回一个生成器
print(g)  # 结果:<generator object generator at 0x103141540>
print(g.__next__())  # 通过next取值

 

生成器函数取值的三种方式:

1.通过__next__()取值:上面的演示代码中已经演示

2.通过for循环取值:

def generator():
    print('生成器函数中打印的数据1')
    yield 1
    print('生成器函数中打印的数据2')
    yield 2
    print('生成器函数中打印的数据3')
    yield 3

g = generator()  # 返回一个生成器

for i in g:
    print(i)

执行结果:
生成器函数中打印的数据1
1
生成器函数中打印的数据2
2
生成器函数中打印的数据3
3

 

3.通过数据类型转换从生成器中取值(比较占用内存):

def generator():
    print('生成器函数中打印的数据1')
    yield 1
    print('生成器函数中打印的数据2')
    yield 2
    print('生成器函数中打印的数据3')
    yield 3


g = generator()
print(list(g))

# 执行结果:
生成器函数中打印的数据1
生成器函数中打印的数据2
生成器函数中打印的数据3
[1, 2, 3]

 

生成器函数与普通函数的区别:

1. 定义方式

  • 普通函数:使用 return 关键字返回一个值,函数执行完毕后结束。
  • 生成器函数:使用 yield 关键字逐个返回值,函数执行可暂停并保持状态。

2. 返回值

  • 普通函数:返回单一值,并终止函数执行。
  • 生成器函数:返回一个生成器对象,可以多次调用,逐个生成多个值。

3. 内存管理

  • 普通函数:一次性生成所有返回值,可能导致高内存占用。
  • 生成器函数:按需生成值,内存占用小,适合处理大数据。

4. 调用方式

  • 普通函数:调用后不可再用,必须重新调用。
  • 生成器函数:可以通过 next() 逐步获取值,也可以在 for 循环中迭代。

5. 状态保持

  • 普通函数:无法保持执行状态,调用后状态丢失。
  • 生成器函数:保持状态,每次调用继续上次暂停的位置。

总结

  • 生成器函数通过 yield 提供了惰性求值的能力,适合需要高效内存管理和逐步生成数据的场景。

生成器表达式

 

标签:__,函数,迭代,Python,18,生成器,next,print
From: https://www.cnblogs.com/mingbo-1/p/18474262

相关文章

  • Python酷库之旅-第三方库Pandas(158)
    目录一、用法精讲721、pandas.Timedelta.round方法721-1、语法721-2、参数721-3、功能721-4、返回值721-5、说明721-6、用法721-6-1、数据准备721-6-2、代码示例721-6-3、结果输出722、pandas.Timedelta.to_pytimedelta方法722-1、语法722-2、参数722-3、功能7......
  • 【并查集+dfs】codeforces 1833 E. Round Dance
    题意输入一个正整数\(T(1\leqT\leq10^4)\),表示接下来输入\(T\)组测试用例,对于每一个测试用例:第一行,输入一个正整数\(n(2\leqn\leq2*10^5)\)第二行,输入\(n\)个正整数\(a_i(1\leqa_i\leqn)\),表示节点\(i\)到节点\(a_i\)存在一条有向边,保证无自环这\(n......
  • 发癫(2024.10.14-2024.10.18)
    虽然已临近CSP复赛,但我还在不务正业更改缺省源最近几天莫名其妙的的想改一下我的缺省源。之前和现在的缺省源比较:之前:#include<stdio.h>#include<string.h>//#include<bits/stdc++.h>//#include<iostream>//usingnamespacestd;//usingstd::cin;#defineitnint#d......
  • TECH.UB.25: Intro to Python Programming
    TECH.UB.25:IntrotoPythonProgramming:Assignment#4Scenario: CampusPizzaisreallytakingoffandyourco-founderslovetheprogramsyouhavebuilt. Theywantyoutobuildanobject-orientedprogramfortheirbeverages. Campuspizzahastwobeve......
  • [ARC185D] Random Walk on Tree 题解
    一个很套路的做法。思路题目要求走完整个树的时间,这并不好算,容易想到min-max容斥。依据min-max容斥,我们可以轻松把它转化成第一次走到所有子集的时间。考虑在这道题中,有什么特殊的。第一,任何包含根节点的子集答案都是零。第二,由于我们只关心第一次走到的点的时间,因此假......
  • 10.18
    10.181、tar-cvf打包格式:tar-cvf***.tar******C打包v显示打包进度f指定文件x解包2、tar-xvf解压格式:tar-xvf压缩包名.tar3、tar.gz包格式:tar-zcvf压缩包名.tar.gz****解压格式:tar-zxvf压缩包名.tar.gz4、zip文件打包格式:zip压缩......
  • 学 Python 还是 Java 更好找工作?
    对于很多想进入编程领域的小伙伴来说,Python和Java这两门编程语言常常让人难以抉择。无论你是新手还是有经验的开发者,选择学习哪一门语言直接关系到未来的职业发展。那么,学Python还是Java更容易找到工作呢?近年来,随着AI、自动化、区块链等技术的崛起,Python的应用逐渐扩展到......
  • (开题)flask框架求职招聘网站atjy7(程序+论文+python)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容选题背景随着互联网技术的迅猛发展,信息传播方式发生了巨大变革。在就业领域,求职招聘的模式也从传统的线下模式逐渐向线上转移。传统的求职招聘方式......
  • 2024.10.18考试总结
    本文于github博客同步更新。A:考虑如果现在在点\(i\),能否走到编号更小的点。如果可以,那么必然存在一个\(j\geqi>a_{j}\)使得你可以走到点\(a_{j}\)。那么我们对于每个\(i\),将区间\(\left(a_{i},i\right]\)加一,从\(x\)开始能走到的编号最小的点也就是\(x\)左侧最......
  • 10.18 模拟赛
    炼石计划10月04日NOIP模拟赛#8【补题】-比赛-梦熊联盟(mna.wang)复盘T1有种div.2B的风格,没秒,想看题。T2。只判是否无解?\(k\le100\)?把\(200\)个关键连通块拿出来建图跑传递闭包不就做完了。一遍过大样例?简直不可思议,但还是把T2关了吧。用分析CF题的方......