python之生成器与模块
生成器对象
生成器对象其实本质还是迭代器,只不过这个迭代器的内容可以由我们直接来定义了,所以它也可以称为自定义迭代器。

先来看一段代码:
def index():
print('abc')
yield
print(index()) # 输出:<generator object index at 0x000001DEEAF00200>
可以看到,在加了关键字yield之后,函数变成了生成器对象了。如果想要执行函数里的代码,就需要使用__next__()方法。
def index():
print('abc')
yield
res = index()
res.__next__() # 输出:abc
多个yield
def index():
print('abc')
yield
print('def')
yield
print('gh')
yield
res = index()
res.__next__() # 输出:abc
res.__next__() # 输出:def
res.__next__() # 输出:gh
在yield后也可以跟上一个值
def index():
print('abc')
yield 123
print('def')
yield 456
res = index()
r1 = res.__next__() # 输出:abc
print(r) # 输出:123
r2 = res.__next__() # 输出:def
print(r) # 输出:456
结论:
- 在函数内部添加了yield关键字之后,函数就会变成生成器对象,并且可以调用__next__方法。
- 当有多个yield关键字时,每执行一次__next__方法时函数代码会运行到下个yield处并停留。
- 如果yield后跟上了一个值,则执行__next__方法时会返回yield后的值。
补充:yield关键字的作用
除了以上的作用外,yield还可以接收外界的传值
def eat(name):
print(f'{name}准备干饭')
while True:
food = yield
print(f'{name}正在吃{food}')
res = eat('jason')
# 使用send方法前需要调用一次__next__启动
res.__next__() # 输出:jason准备干饭
# 使用send方法给yield传值
res.send('kfc') # 输出:jason正在吃kfc
res.send('米饭') # 输出:jason正在吃米饭
自定义range方法
在了解完生成器对象后,这时候我们就可以自己定义一个和range一样功能的方法了。
先实现两个参数的情况:
def my_range(start, end):
"""
start: 起步位置
end: 结束位置
"""
# 如果start一直累加后值等于end则退出循环
while start < end:
yield start
# 每被执行一次__next__方法起始位置加1
start += 1
for i in my_range(1, 4):
print(i)
实现了两个参数后,我们可以开始解决一个参数的情况
def my_range(start, end=None):
"""
start: 起步位置
end: 结束位置,默认为空值
"""
# 如果没有给end传值,说明只有一个参数,取值范围为[0,start)
if not end:
end = start
start = 0
# 如果start一直累加后值等于end则退出循环
while start < end:
yield start
# 每被执行一次__next__方法起始位置加1
start += 1
for i in my_range(1, 4):
print(i)
最后解决三个参数的情况
def my_range(start, end=None, step=1):
"""
start: 起步位置
end: 结束位置,默认为空值
step:步长,默认为1
"""
# 如果没有给end传值,说明只有一个参数,取值范围为[0,start)
if not end:
end = start
start = 0
# 如果start一直累加后值等于end则退出循环
while start < end:
yield start
# 每被执行一次__next__方法起始位置加步长
start += step
for i in my_range(1, 4):
print(i)

生成器表达式
直入主题,生成器结构
res = (i for i in 'jason')
print(res) # 输出:<generator object <genexpr> at 0x000002AC49CF0200>
"""可以看到,它并不会像列表生成式一样直接输出"""
"""因为生成器内部的代码只有在调用__next__迭代取值的时候才会执行"""
print(res.__next__()) # 输出:j
print(res.__next__()) # 输出:a
模块
简介
模块就是一系列功能的结合体,只需要导入就可以直接使用,它极大的提升了开发效率。比如我自己要实现一个功能可能要写好几行代码,但是如果模块里可以实现这个功能,那我可以直接拿来使用。
模块的三种来源方式:
内置的模块
这些是python自带的模块,直接用代码导入就可以使用。
自定义模块
这些是自己写的代码封装成模块,可以自己使用或发布到网上
第三方模块
这些是由别人发布到网上的,我们可以下载过来使用
模块的四种表现形式:
- 使用python代码编写的py文件
- 多个py文件组成的文件夹,也可以称为包
- 已被编译为共享库或DLL的c或C++扩展(了解)
- 使用C编写并链接到python解释器的内置模块(了解)

模块的导入方式
第一种:import ...
语法结构:
import 模块1, 模块2, ...
这种导入方式可以使用模块内部的变量和方法,一个模块只会被导入一次,不管你执行了多少次import。
案例一:
创建一个md.py文件
name = '来自md.py'
print(name)
创建一个main.py文件
import md
执行main.py文件,此时会输出
来自md.py
说明在导模块时,会执行被导入模块的内部代码。
案例二:
创建一个md.py文件
name = '来自md.py的name变量'
def index():
print('来自md.py的index函数')
创建一个main.py文件
import md
name = '来自main.py的name变量'
print(name)
print(md.name)
def index():
print('来自main.py的index函数')
index()
md.index()
执行main.py文件,此时会输出
来自main.py的name变量
来自md.py的name变量
来自main.py的index函数
来自md.py的index函数
说明导入模块后,想要模块内部变量和函数需要使用模块加点的方式,直接使用只会从当前文件寻找。
图解:

第二种:from ... import ...
语法结构:
from 模块名 import 名称1,名称2,...
这种方式使用模块内部的名称可以不需要用模块加点的方式了,可以直接使用。
案例一:
创建一个md.py文件
name = '来自md.py'
print(name)
创建一个main.py文件
from md import name
执行main.py文件,此时会输出
来自md.py
说明在导模块时,会执行被导入模块的内部代码。
案例二:
创建一个md.py文件
name = '来自md.py'
def index():
print('来自md.py的index函数')
创建一个main.py文件
from md import name, index
print(name)
index()
执行main.py文件,此时会输出
来自md.py
来自md.py的index函数
说明使用from + import方法导入模块后,可以直接使用模块内部的名称,所以这时候就需要避免出现重名的情况。
图解

补充
- 导入模块时可以给模块起别名
import time as t
t.sleep(3) # 等价于time.sleep(3)
from md import name as n, index as x
print(n) # 等价于print(name)
x() # 等价于index()
- 导入全部名称
from md import *
"""如果模块文件中使用了__all__限制可以使用的名字,那么*号就会失效,只能使用__all__后面列举的名字"""
# 在md.py文件中
__all__ = ['name']
# 这时如果使用from md import *只能使用name变量
- 建议
导入个模块时,可以把有相似功能的模块使用同一个import导入,如果没有建议分开导入。

python之生成器与模块的更多相关文章
- Python迭代器生成器,模块和包
1.迭代器和生成器 2.模块和包 1.迭代器 迭代器对象要求支持迭代器协议的对象,在Python中,支持迭代器协议就是实现对象的__iter__()和__next__()方法. 其中__it ...
- Python推导表达式、迭代器、生成器、模块和包
推导表达式 yield用法 模块的概念和导入方法 包和包管理 推导表达式(利用for,一个一个地放入数据) 列表推导 集合推导 字典推导 迭代器 迭代 for 迭代变量 in 可迭代对象 每一次循环都 ...
- python学习之random模块
Python中的random模块用于生成随机数.下面介绍一下random模块中最常用的几个函数. random.random random.random()用于生成一个0到1的随机符点数: 0 < ...
- python笔记之itertools模块
python笔记之itertools模块 itertools模块包含创建有效迭代器的函数,可以用各种方式对数据进行循环操作,此模块中的所有函数返回的迭代器都可以与for循环语句以及其他包含迭代器(如生 ...
- 【转】Python 3的pathlib模块:驯服文件系统
[转]Python 3的pathlib模块:驯服文件系统 https://python.freelycode.com/contribution/detail/1248 Python部落(python. ...
- python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解
一.生成器 1.什么是生成器? 在python中,一边循环一边计算的机制,称为生成器:generator. 2.生成器有什么优点? 1.节约内存.python在使用生成器时对延迟操作提供了支持.所谓延 ...
- Python高级编程-itertoos模块
Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数. 首先我们看看itertools模块提供的几个“无限”迭代器, import itertools naturals = ...
- python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解
python中"生成器"."迭代器"."闭包"."装饰器"的深入理解 一.生成器 1.生成器定义:在python中,一边 ...
- python基础,函数,面向对象,模块练习
---恢复内容开始--- python基础,函数,面向对象,模块练习 1,简述python中基本数据类型中表示False的数据有哪些? # [] {} () None 0 2,位和字节的关系? # ...
随机推荐
- link和@import的区别浅析
我们都知道,外部引入 CSS 有2种方式,link标签和@import.它们有何本质区别,有何使用建议,在考察外部引入 CSS 这部分内容时,经常被提起. 如今,很多学者本着知其然不欲知其所以然的学习 ...
- 为什么局部内部类访问外边的局部变量必须为final
6.局部内部类访问外边的局部变量时,此变量必须为final类型 马克-to-win:由于技术方面的限制,java的设计者们做出如下语法规定:局部内部类访问外边的局部变量时,此变量必须为final类型, ...
- 何使用派生类指针指向基类,即downcast向下转型?
基类指针指向派生类,我们已经很熟了.假如我们想用派生类反过来指向基类,就需要有两个要求:1)马克-to-win:基类指针开始时指向派生类,2)我们还需要清清楚楚的转型一下. if you want t ...
- PAT B1091 N-自守数
输入样例: 3 92 5 233 输出样例: 3 25392 1 25 No '解题思路:判断的时候将结果转换成字符串,判断后面几位数字和输入数字是否相同,掉进了N是从1到10的坑,而不是1到9 ...
- 关键字static、extern、volatile、详解及举例
一.预备知识 1. 什么是局部变量?什么是全局变量? 所谓局部变量,就是指在函数内部定义的变量的,只在该函数范围内有效. 全局变量是指,在函数外部定义的变量为外部变量,即全局变量.它 ...
- C#多线程下的调优
一.原子操作 先看一段问题代码 /// <summary> /// 获取自增 /// </summary> public static void GetIncrement() ...
- @RequestBody和@RequestParam注解以及返回值,ajax相关知识点
关于前后端传递json数据这块查了好多资料,好多地方还是不清楚,先记录一下清楚的地方. 如果我们前端使用ajax发json数据,一般都加上contentType:'application/json;c ...
- SpringMVC 解析(五)URI链接处理
URI在网络请求中必不可少,Spring提供了一些工具类用于解析或者生成URL,比如根据参数生成GET的URL等.本文会对Spring MVC中的URI工具进行介绍,本文主要参考Spring官方文档. ...
- HTML5+JavaScript+MUI 毕业答辩常见问题
问题1:HTML5前端开发环境有哪些? HTML5网页前端开发,实际也是HTML网页开发,HTML5知识万维网的核心语言.标准通用标记语言下的一个应用超文本标记语言(HTML)的第五次重大修改的第五次 ...
- Postman+newman+jenkins+git实战
一.接口分类,流程,用例设计 接口分类: 外部接口:被测系统与外部其他系统之间的接口. 承保系统(被测系统),核算系统. 内部接口:被测系统内部各个子模块之间的接口. 承保系统(A模块,B模块) 测试 ...