今日学习目标:
- 学习生成器对象、 模块简介
今日学习内容:
内容简要:
- 生成器对象(自定义迭代器)
- 模块简介
内容详细:
生成器对象(自定义迭代器)
生成器本质是一个使用了yield返回值的函数,支持使用next()函数不断返回下一个值,同时支持使用send函数向生成器发送消息。
生成器对象也是节省存储空间的 特性与迭代器对象一致,所以也可以说是特殊的迭代器。
-
特点
- 当函数体代码中含有yield关键字,第一次调用函数并不会执行函数体代码,而是将函数变成了生成器
- yield执行并返回值后,不会退出函数体,而是挂起,待下次next时,再从挂起点恢复运行,如果没有了 再执行也会报错 StopIteration。
- yield语句可以接受通过生成器send方法传入的参数并赋值给一个变量,以动态调整生成器的行为表现
-
举例
def index(): yield 123 yield 666 # 没有调用之前 就是一个普通的函数 print(index) # <function index at 0x0000021C768AD5E0> # 加括号调用并接收结果:不执行代码 而是变成生成器对象(迭代器) res = index() print(res) # <generator object index at 0x0000021C768A3E40> # 变成生成器对象之后调用__next__就会开始执行函数体代码 print(res.__next__()) # 123 yield有点像return的功能 print(res.__next__()) # 666 yield有点像return的功能 # print(res.__next__()) # 报错
运行结果
-
实际应用案例
需求:通过生成器模拟range方法def my_range(start, end=None, step=1): if not end: end = start start = 0 while start < end: yield start start += step for i in my_range(1,10): print(i)
-
yield详解及与return对比
- 相同点:
- 均在函数体内使用,并且向调用方返回结果
- 均可返回一个值或多个值,如果是多个值,则是以元组格式返回
- 不同点:
- 包含yield的函数,调用时最终返回的是一个生成器,单纯的return函数,调用时返回的是一个值。
- return 执行并返回值后,便会直接退出函数体,该函数内存空间即回收释放
- yield执行并返回值后,不会退出函数体,而是挂起,待下次next时,再从挂起点恢复运行
- yield语句可以接受通过生成器send方法传入的参数并赋值给一个变量,以动态调整生成器的行为表现
- return在生成器中的作用:
在一个生成器函数中,如果没有 return,则默认执行至函数完毕,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代
#1、yield和return共存 def gene(maxcount): a,b=0,1 count=1 while True: if count>maxcount: #直接退出函数体 return else: #返回值后,函数在该处挂起,下次再从该处恢复运行 yield a+b a,b=b,a+b count+=1 #2、yield接受通过send传入的参数并动态调整生成器行为 def gene(maxcount): a,b=0,1 count=1 while True: if count>maxcount: return else: msg=yield a+b if msg=='stop': return a,b=b,a+b count+=1 g=gene(10) next(g) g.send('msg') #生成器终止,并抛出一个StopIteration异常
- 相同点:
模块简介
-
什么是模块?
模块就是一系列功能的结合体 可以直接使用,实际上就是 以.py为结尾的文件(注意点:自定义的模块尽量不要和系统模块重名) -
为什么要用模块?
极大地提升开发效率,因为它是一些功能的集合体,所以在程序编写的过程中,一些别人已经写好的功能就可以用调用替代繁重的自我编写。 -
模块的三种来源
- 内置的模块
无需下载 解释器自带 直接导入使用即可 - 自定义模块
自己写的代码 封装成模块 自己用或者发布到网上供别人使用 - 第三方模块
别人写的发布到网上的 可以下载使用的模块
- 内置的模块
-
模块的四种表现形式
- 使用python代码编写的py文件
- 多个py文件组成的文件夹(包)
- 已被编译为共享库或DLL的c或C++扩展
- 使用C编写并链接到python解释器的内置模块
-
模块的两种导入方式
方式1>>>:
import...句式
方式2>>>:from...import...句式
详细语法
- improt 模块名
调用:模块名.功能名 - import 模块名 as 别名
调用:别名.功能名 - from 模块名 import 功能名
调用:直接功能名 - from 模块名 import 功能名 as 别名
调用: 直接拿别名来用 - from 模块名 import * (用 * 号 一次性导入所有功能)
调用:直接功能名
注意点:* 号没法用别名
- improt 模块名
-
import...句式
前提:在研究模块的时候 一定要分清楚谁是执行文件 谁是被导入文件(模块)
- 导入模块内部到底发送了什么事情
- 执行当前文件 产生一个当前文件的名称空间
- 执行import句式 导入模块文件(即执行模块文件代码产生模块文件的名称空间)
- 在当前文件的名称空间中产生一个模块的名字 指向模块的名称空间
- 通过该名字就可以使用到模块名称空间中的所有数据
-
import句式的特点
可以通过import后面的模块名点的方式 使用模块中所有的名字,并且不会与当前名称空间中的名字冲突
-
from...import...句式
前提:在研究模块的时候 一定要分清楚谁是执行文件 谁是被导入文件(模块)
- 导入模块内部到底发送了什么事情
- 执行当前文件产生一个名称空间
- 执行导入语句 运行模块文件产生名称空间存放运行过程中的所有名字
- 将import后面的名字直接拿到当前执行文件中
- from…import…句式
- 重复导入也只会导入一次
- 使用模块名称空间中的名字不需要加模块名前缀 直接使用即可
- 但是from…import的句式会产生名字冲突的问题,在使用的时候 一定要避免名字冲突
- 使用from…import的句式 只能使用import后面出现的名字
特别说明
- from md import *
from...import的句式也可以导入所有的名字
如果模块文件中使用了__ all__限制可以使用的名字 那么*号就会失效 依据__ all__后面列举的名字
- 使用方式
import...句式调用发生的那些事
from...import...句式调用发生的那些事
今日学习时间:
这里统计计划学习的时间
1、 上午8:30~12:30
2、 下午2:30~5:30
3、 晚上6:30~9:30
今日学习产出:
这里统计学习计划的总量
- 1、 技术笔记 1遍
- 2、CSDN 技术博客 1篇
- 3、每日录音,预习明日内容