生成器对象
# 本质还是迭代器 只不过是通过我们自己写代码而生成
也有__iter__方法和__next__方法
def index():
print('hello')
yield 123
print('jason')
yield
# 生成器对象也是节省存储空间的,特性与迭代器对象一致
'''
当函数体代码中含有yield关键字的时候,第一次调用并不会执行函数体代码,而是将函数变成生成器
'''
print(index) # <function index at 0x000002B564DF1F28> 不进行调用就是普通的函数
print(index()) # <generator object index at 0x000002B5654C0A98> 调用后就会变成生成器
# 当函数变成生成器之后,可以通过调用__next__()来执行函数体代码
# 先调用函数
res = index()
next(res) # 'hello'
next(res) # 'jason'
next(res) # 报错
'''当函数体代码中含有多个yield关键字的时候 执行一次__next__()yield上面的代码就会被执行,并停留在yield
再次执行__next__()就会基于上此停止的位置继续往后执行到下一个yield,如果下面没有yield就会报错'''
自定义range方法
# range方法是一个可迭代对象
通过生成器模拟range方法
def my_range(start,end=False,step=1):
if not end:
end = start
start = 0
while start < end:
yield start
start += step
for i in my_range(5):
print(i)
yield关键字的作用
# 1.在函数体代码中出现 可以将函数变成生成器
# 2.在执行过程中可以将后面的值返回出去 类似return
# 3.还可以暂停代码的运行
# 4.还可以接收外界的传值
def eat(name):
print('hello')
while True:
name = yield
print(name)
res = eat('jason')
next(res) # hello
next(res) # None
res.send('drink') # drink send可以给yield传值,并自动调用一次__next__
生成器表达式
# 也是为例节省存储空间
后期进行代码的优化的时候可以考虑使用
res = (i for in 'jason')
# res 就是生成器对象
'''生成器内部的代码只有在调用__next__迭代取值的时候才会执行'''
#题目实战
def add(n, i):
return n + 1
def test():
for i in range(4):
yield i
g = test()
for n in [1, 10]
g = (add(n, i) for i in g)
res = list(g)
print(res)
res = [20,21,22,23]
模块
'''
很多大佬写了很多很厉害的模块 供python工程师直接使用,因此当我们遇到一个非常复杂的功能需要实现的时候,第一时间相对应该是取网上能不能找到想应的模块
'''
# 什么是模块
模块就是一系列功能的结合体,可以直接使用
# 为什么要用模块
极大的提升开发的效率
# 模块的三种来源
1.内置的模块
无需下载 解释器自带 直接导入即可
2.自定义模块
自己写的代码封装成模块自己使用或者发布到网上供别人使用
3.第三方模块
别人写的发布到网上的 可以下载使用的模块
# 模块的四种表现形式
1.使用python代码编写py文件
2.多个py文件组成的文件夹
3.已被编译为共享库或DLL的C或C++扩展
4.使用c编写并链接到python解释器的内置模块
模块的两种导入方式
# 使用模块前,必须先进行导入,而导入的方法有两种
# 方式1>>>:import 包名
比如导入time模块
import time
'''
一定要分清谁是执行文件,谁是导入文件(模块)
导入模块内部发生了什么
1.执行当前文件 产生一个当前文件的名称空间
2.执行import句式 导入模块文件(即执行模块文件代码模块文件的名称空间)
3.在当前文件的名称空间中生成一个模块的名字,指向模块的名称空间
4.通过在执行文件中生成的名字可以使用模块名称空间中的所有数据
'''
# import句式的特点
1.相同模块重复导入只会被执行一次
2.可以通过import后面的模块点名的方式,使用模块中所有的名字
3.模块当中的名字不会和执行文件中的名字冲突
# 方式2:from 模块名 import 方法名
from time import time,tzset
'''
1.执行当前文件产生一个名称空间
2.执行导入语句 运行模块文件产生名称空间,存放运行中产生的所有名字
3.将import后面的名字直接拿到执行问价中
'''
# 该方式的特点
1.重复导入只会执行一次
2.使用模块名称空间中的名字不需要加模块名前缀,直接使用即可
3.导入的名称会与执行文件中的名称产生冲突。因为他是直接将模块中的方法存放到执行文件的名称空间
4.使用from...import...的句式,只能使用import中出现的名字
![]()
![]()
导入补充
# 1.可以给模块起别名,比如当模块名称非常复杂的时候可以用简单的别名代替
import time as t
就是将time模块的名称替换成t 调用方法的时候直接t.就行
# 2.连续导入多个模块或者变量名
import time, sys, md
from md import name, read1, read2
"""
连续导入多个模块 这多个模块最好有相似的功能部分 如果没有建议分开导入
如果是同一个模块下的多个变量名无所谓!!!
"""
# 3.通用导入
from md import *
*表示md里面所有的名字
但是 如果模块中使用了__all__限制可以使用的名字 那么*就会失效 依据的是__all__后面列举的名字