生成器对象
# 生成器对象的本质还是迭代器,只不过使我们自己通过写代码产生的
'''生成器对象也有__iter__和__next__方法'''
eg:
def index():
print('我执行了')
yield
res = index()
print(res)
运行结果:
<generator object index at 0x0158FB70>
# 上述代码可以看到,当我们函数里面有yield关键字时,第一次调用函数时,返回的是一个迭代器对象,也就是我们说的生成器
'''生成器对象也是节省存储空间的 特性与迭代器对象一致'''
"""
当函数体代码中含有yield关键字
第一次调用函数并不会执行函数体代码
而是将函数变成了生成器
生成器可以点出__iter__和__next__方法
"""
# yield关键字:当函数体代码中有yield关键字时,第一次运行把函数变成生成器,后面在调用__next__方法时,每调用一次,执行到一个yield停止,当程序里所有的yield被调用完时,再调用会和迭代器一样报错StopIteration
eg:
def index():
print('伞兵一号')
yield 123
print('伞兵二号')
yield 456
print('伞兵三号')
yield 789
res = index()
print(res.__next__())
print(res.__next__())
print(res.__next__())
运行结果:
伞兵一号
123
伞兵二号
456
伞兵三号
789
# yield也有return的传递返回值的作用
自定义range方法
# 不废话,直接上代码!!!
eg:
# 自定义range方法
def my_range(start, end=0, step=1):
# 2. 当只输一个数时,默认start = 0,end = 输入的参数
if end == 0:
start, end = end, start
# 1. 当没有到末尾数时,依据步长递增输出,步长默认为1
while start < end:
yield start
start += step
for i in my_range(5,10,2):
print(i)
运行结果:
5
7
9
'''
分析:
range(start,end,step)
range方法有三个参数,起始数,末尾数,步长,根据这三个参数的规定造一个可以生成等差数列的老母猪,你用他就搁那,不占空间,需要一个数就给一个
1. 传一个参数,start使用默认值0,step使用默认值1,实参给end
2. 传两个参数,两个位置实参给start,end,step使用默认值1
3. 传三个参数,按照顺序给start,end,step
'''
yield关键字作用
yield关键字作用汇总:
# 1.在函数体代码中出现 可以将函数变成生成器
# 2.在执行过程中 可以将后面的值返回出去 类似于return
# 3.还可以暂停住代码的运行
# 4.还可以接收外界的传值(了解):send方法
eg:
def index():
a = yield '666'
yield '777'+ a
res = index()
print(res.__next__())
print(res.send('888'))
运行结果:
666
777888
'''
yield传值重点:
1. 使用send时,必须先执行一次__next__
2. send传值之后,会自动向后迭代一次
'''
生成器表达式
# 之前学各种生成式的时候就说了,没有元组生成式,因为元组生成式就是生成器
eg:
res = (i for i in [1,2,3,4,5] if i != 5)
print(res)
print(res.__next__())
运行结果:
<generator object <genexpr> at 0x00E8F390>
1
# 语法很像我们之前学的各种生成式,但是结果是一个生成器对象
"""生成器内部的代码只有在调用__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是多少即可"""
模块
"""
python之所以很火并且适用于各行各业很大程度上的原因就是>>>:模块
很多大佬写了很多非常牛逼的模块 供python工程师直接使用(白嫖)
eg:
import time 导入模块
time.time() 调用方法
python刚开始出来的时候被很多其他语言的程序员看不起 嘲笑python是一个
调包侠
(只会调用别人写好的东西,拿来主义跟传统价值观不一致>>>:自己动手丰衣足食) 此时的调包侠是贬义词
但是当其他语言的程序员开始写python用到了模块之后发现'真香' 调包侠真好用 真牛逼 我好喜欢 此时的调包侠是褒义词
ps:作为一名python工程师CV大法都要比其他工程师练得更加炉火纯青!!!
温馨提示:作为一名python工程师 如果遇到一个非常复杂的功能需要实现 那么第一时间不是想着如何去写 而是去网上找有没有相应的python模块!!!
以后出去工作了之后才应该考虑的
eg:人脸识别 语言转换 自动感应 类似更本摸不着头脑的几乎都有模块
"""
# 1. 什么是模块?
模块就是写好的功能代码块,需要这个功能可以直接拿来拼接到自己的代码上面使用
# 2. 为什么要用模块?
极大地提高开发效率,可以快速完成项目编写
# 3. 模块的三中来源
1. 内置模块(time,sys等)
解释器自带的,直接导入是即可
2. 自定义模块
自己写的代码,封装成模块,非常吊的模块可以发布到网上供别人使用
3. 第三方模块
别人写的发布到网上的,可以下载使用的模块
# 4. 模块的四种表现形式
1.使用python代码编写的py文件 # 掌握
2.多个py文件组成的文件夹(包) # 掌握
3.已被编译为共享库或DLL的c或C++扩展(了解)
4.使用C编写并链接到python解释器的内置模块(了解)
模块的两种导入方式
"""要想使用模块 必须先导入 而导入的方法有两种"""
# 方式一:import...句式
eg:
import time # 导入time包
print(time.time()) # 调用time包的方法
'''
在研究模块的时候,一定要搞清楚谁是执行文件,谁是被导入文件
import time
import在哪个文件里,哪个文件就是执行文件
import后面跟的名字就是被导入文件的名字
导入模块内部到底发生了什么事情?
1. 执行当前文件,产生一个当前文件的名称空间
2. 执行import句式,导入模块文件,执行模块文件产生模块文件的名称空间
3. 在当前文件的名称空间产生一个名字,指向模块名称空间,这个名字相当于模块文件的户口本
4. "通过户口本上的名字找人",就可以调用用到模块名称空间的数据
ps:反复导入同一模块,只会执行一次,pycharm中,这样导入后,模块被调用了,只有一个import会高亮显示
'''
# 如何调用模块名称空间的名字
'''模块名.模块空间中的名字'''
# 在pycharm中,当你的import句式生效后,使用模块名加点可以提示模块名称空间中的所有名字
# 当两个名称空间有同样的名字时,直接调用是使用执行文件的,模块名点调用的是模块文件的,不会冲突
==========================================================
# 方式二:from...import...句式
eg:
from time import time
print(time())
运行结果:
1648114270.873182
# 这个句式导入的是模块内部的名字,导入哪个名字只能用哪个名字,上述代码我导入了time模块里的time方法,再用time点就点不出来方法了
"""
1.执行当前文件产生一个名称空间
2.执行导入语句 运行模块文件产生名称空间存放运行过程中的所有名字
3.将import后面的名字直接拿到当前执行文件中
"""
"""
1.重复导入也只会导入一次
2.使用模块名称空间中的名字不需要加模块名前缀 直接使用即可
3.但是from...import的句式会产生名字冲突的问题
在使用的时候 一定要避免名字冲突
4.使用from...import的句式 只能使用import后面出现的名字
from...import...可以简单的翻译成中文
从...里面拿...来用 没有提到的都不能用 指名道姓
"""
import...句式导入模块内部结构
from...import...句式导入模块内部结构
导入补充
# 1. 给导入模块起别名
# import time as t
# from time import time as t1
# print(t.time())
# print(t1())
# >>>1648115654.0233126
# >>>1648115654.0233126
# 貌似所有的起别名都是'as 别名'
# 2. 连续导入多个模块
# import time,sys
# from time import time,sleep
"""连续导入多个模块 这多个模块最好有相似的功能部分 如果没有建议分开导入
如果是同一个模块下的多个变量名无所谓!!!
"""
# 3.通用导入
from md import *
'''*表示md里面所有的名字 from...import的句式也可以导入所有的名字
如果模块文件中使用了__all__限制可以使用的名字 那么*号就会失效 依据__all__后面列举的名字
'''