Python基础篇---生成器和模块
本章内容
• 生成器对象
• 自定义range方法
• yield关键字作用
• 生成器表达式
• 模块
生成器对象
生成器对象其本质是自定义迭代器,就是需要我们自己写代码产生的迭代器。
生成器对象也是节省存储空间的 特性与迭代器对象一致。
def index(): print('第一次输出') yield 1 print('第二次输出') yield 2
1 2 3 4 5 6 7 8 9 10 | 当我们没有加括号调用之前,它就是一个普通的函数 print(index) # <function index at 0x1096c0ea0> 加括号调用并接收结果,不执行代码,而是变成生成器对象(迭代器) res = index() # print(res) # <generator object index at 0x11da33468> res有了iter()和next()方法 变成生成器对象之后调用__next__就会开始执行函数体代码 调用一次next: print(res.__next__()) #第一次输出 1 yield有点像 return 的功能 停止在这里 print(res.__next__()) #第二次输出 2 print(res.__next__()) # 报错 |
如果函数体代码中含有多个yield关键字 执行一次__next__返回后面的值并且让代码停留在yield位置,
再次执行__next__基于上次的位置继续往后执行到下一个yield关键字处,
如果没有了 再执行也会报错。
自定义range方法
range方法其实是一个可迭代对象。
需求:通过生成器模拟range方法。
def my_range(): pass for i in my_range(1,10): print(i)
先实现range2个参数的最简单情况。
def range(start, end): # start为开始 end为结束 while start < end: # 设置一个循环 去迭代start+1 yield start # 每一次循环都返回start start += 1 # 迭代 for i in range(1, 10): print(i)
特殊情况,只有一个参数的情况。
def range(start, end=None): # start为末尾值 end可以不传值 应该设置成默认参数 if not end: # 没有给end传值 end=None 代码层面做判断 将形参数据做替换处理 end = start start = 0 while start < end: # 设置一个循环 去迭代x+1 yield start # 每一次循环都返回x start += 1 # 迭代 for i in range(1, 10): print(i)
三个参数情况,传入了步长。
def range(start, end=None,step=1): # 给函数添加第三个形参 并且设置成默认参数 默认值是1 step=1 if not end: # 没有给end传值 end=None 代码层面做判断 将形参数据做替换处理 end = start start = 0 while start < end: # 设置一个循环 去迭代x+1 yield start # 每一次循环都返回x start += step # 每次递增的时候只需要递增step的数值即可 for i in range(1, 10): print(i)
写代码一定不要想太多,先搭建主题功能,之后再考虑其他情况,思路一定要清晰!!!
1 2 3 4 5 | yield的作用: 在函数体代码中出现 可以将函数变成生成器 在执行过程中 可以将后面的值返回出去 类似于 return 还可以暂停住代码的运行 还可以接收外界的传值(了解) |
def go_home(name): print(f'{name}在回家路上') while True: home= yield print(f'{name}到家了{home}') res = go_home('jason') # 想执行一次代码 如果想执行多次直至结束 可以直接用for循环 res.__next__() res.__next__() # 给yield传值 res.send('没有钥匙') # 可以给yield传值 并且自动调用一次__next__方法 res.send('有钥匙') # 可以给yield传值 并且自动调用一次__next__方法
生成器表达式也是为了节省存储空间,用来做代码优化,前期学习可以忽略。
# 生成器表达式 res = (i for i in 'jason') print(res) # <generator object <genexpr> at 0x0000022C8D360D00> print(res.__next__()) # j print(res.__next__()) # a print(res.__next__()) # s """生成器内部的代码只有在调用__next__迭代取值的时候才会执行"""
下面有一个生成器表达式的例题,诀窍在于生成器的调用。
# 普通的求和函数 def add(n, i): return n + i # 生成器对象 返回 0 1 2 3 def test(): for i in range(4): yield i # 将test函数变成生成器对象 g = test() # 简单的for循环 for n in [1, 10]: g = (add(n, i) for i in g) """ 第一次for循环 g = (add(n, i) for i in g) 第二次for循环 g = (add(10, i) for i in (add(10, i) for i in g)) """ res = list(g) # list底层就是for循环 相当于对g做了迭代取值操作 print(res) #A. res=[10,11,12,13] #B. res=[11,12,13,14] #C. res=[20,21,22,23] #D. res=[21,22,23,24] """正确答案是C 诀窍就是抓n是多少即可"""
模块
简介
模块就是一系列功能的结合体,可以直接使用,极大地提升开发效率。
模块的三种来源
1 2 3 4 5 6 | 内置的模块 无需下载 解释器自带 直接导入使用即可 自定义模块 自己写的代码 封装成模块 自己用或者发布到网上供别人使用 第三方模块 别人写的发布到网上的 可以下载使用的模块(很多牛逼的模块都是第三方) |
模块的四种表现形式
1 2 3 4 | 使用python代码编写的py文件 # 掌握 多个py文件组成的文件夹(包) # 掌握 已被编译为共享库或DLL的c或C++扩展(了解) 使用C编写并链接到python解释器的内置模块(了解) |
要想使用模块,必须先把模块导入,而导入的方法有两种。
方式1---import...句式
import md # 导入md模块 print(md.name) #调用md模块中的名称 md.read1() # 调用md模块里的函数
import句式的特点
1 2 | 可以通过import后面的模块名点的方式 使用模块中所有的名字 并且不会与当前名称空间中的名字冲突(指名道姓) |
模块导入的原理
1 2 3 4 5 6 7 8 | 执行当前文件 产生一个当前文件的名称空间 执行import句式 导入模块文件(即执行模块文件代码产生模块文件的名称空间) 在当前文件的名称空间中产生一个模块的名字 指向模块的名称空间 通过该名字就可以使用到模块名称空间中的所有数据 ps:相同的模块反复被导入只会执行一次 import md 有效 import md 无效(写了跟没写一样) import md 无效(写了跟没写一样) |
方式2---from...import...句式
from md import name # 导入模块中的名称name 其他的没有导入进来 print(name) # jasonNB name = 'kevin' print(name) # kevin
from...import...句式特点
1 2 3 4 | 重复导入也只会导入一次 使用模块名称空间中的名字不需要加模块名前缀,直接使用即可 但是 from ...import的句式会产生名字冲突的问题,在使用的时候 一定要避免名字冲突 使用 from ...import的句式 只能使用import后面出现的名字,没有出现的用不了 |
from...import...的原理
1 2 3 | 执行当前文件产生一个名称空间 执行导入语句 运行模块文件产生名称空间存放运行过程中的所有名字 将import后面的名字直接拿到当前执行文件中 |
模块
使用场景:模块名或者变量名很复杂,可以起别名简写 import md as m print(m.name) from md import name as n print(n)
2.连续导入多个模块或者变量名
import time, sys, md from md import name, read1, read2 # 连续导入多个模块,这多个模块最好有相似的功能部分,如果没有建议分开导入,如果是同一个模块下的多个变量名无所谓!!!
3.通用导入
from md import * # *表示md里面所有的名字 from...import的句式也可以导入所有的名字 # 如果模块文件中使用了__all__限制可以使用的名字 # 那么*号就会失效 依据__all__后面列举的名字
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人