生成器和模块

生成器对象

# 生成器对象的本质还是迭代器,只不过使我们自己通过写代码产生的
	'''生成器对象也有__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__后面列举的名字
'''

猜你喜欢

转载自blog.csdn.net/m0_59485658/article/details/128666887