0
点赞
收藏
分享

微信扫一扫

逆袭之路——python生成器对象、模块、导入模块【day17】

自信的姐姐 2022-03-24 阅读 111

今日内容概要

  • 生成器对象(自定义迭代器)
  • 自定义range方法
  • yield关键字作用
  • 生成器表达式
  • 模块
  • 模块的两种导入方式
  • 导入补充
    在这里插入图片描述

今日内容详细

一、生成器对象(自定义迭代器)

  • 本质其实还是迭代器 只不过是我们自己通过写代码产生
    也是有__iter__和__next__方法
def index():
    # print('你还记得我吗?')
    yield 123
    # yield 123, 111
    # print('是不是忘记我了!!!')
    yield 666
'''生成器对象也是节省存储空间的 特性与迭代器对象一致'''
"""
当函数体代码中含有yield关键字
    第一次调用函数并不会执行函数体代码
    而是将函数变成了生成器
如何验证?
    是否有iter()和next()方法
"""
# 没有调用之前 就是一个普通的函数
# print(index)  # <function index at 0x1096c0ea0>
# 加括号调用并接收结果:不执行代码 而是变成生成器对象(迭代器)
res = index()
# print(res)  # <generator object index at 0x11da33468>
# 变成生成器对象之后调用__next__就会开始执行函数体代码
# print(res.__next__())  # 123  yield有点像return的功能
# print(res.__next__())  # (123, 111)  yield有点像return的功能
# print(res.__next__())  # 666
# print(res.__next__())  # 报错
for i in res:
    print(i)
"""
如果函数体代码中含有多个yield关键字  执行一次__next__返回后面的值并且让代码停留在yield位置 
再次执行__next__基于上次的位置继续往后执行到下一个yield关键字处
如果没有了 再执行也会报错  StopIteration
"""

二、自定义range方法

  • range方法其实是一个可迭代对象
  • range()函数有三个参数,分别是start, stop和step。准确的说range()函数将返回一个从start到stop,步长为step的整数序列的对象。
  • range()的类型是一个整数序列对象,而不是列表,但是可以用list()函数返回该对象的列表。
  • range的使用可以是单参数双参数三参数
    单参数: range(10)
    返回一个从 0 到 10 的整数序列的对象,默认步长 step = 1
    单参数中所传参数为stop,默认start = 0, step = 1
    双参数
    返回一个从start到stop的整数序列的对象, 默认步长 step = 1
    range(2, 10)
    返回一个从2到10的整数序列的对象 , 默认步长step = 1
    三参数: 返回一个从start到stop的整数序列的对象, step 为第三个参数的值
    range(2, 10, 2)
    list(range(2, 10, 2))
    从 整数 2 开始 ,每2个整数取一位放到整数列表中,到整数10结束(不包括整数10)

三、 yield关键字作用

  1. 在函数体代码中出现 可以将函数变成生成器
  2. 在执行过程中 可以将后面的值返回出去 类似于return
  3. 还可以暂停住代码的运行
  4. 还可以接收外界的传值(了解)
def eat(name):
    print(f'{name}准备干饭')
    while True:
        food = yield
        print(f'{name}正在吃{food}')
res = eat('赵公子')
# 想执行一次代码  如果想执行多次直至结束 可以直接用for循环
res.__next__()
# res.__next__()  赵公子正在吃None
# res.__next__()  赵公子正在吃None
res.send('生日蛋糕')  # 可以给yield传值 并且自动调用一次__next__方法
res.send('大鸡腿')  # 可以给yield传值 并且自动调用一次__next__方法

四、生成器表达式

# 也是为了节省存储空间
	在后期我们做代码优化的时候 可以考虑使用  前期学习阶段可以忽略
 
# res = (i for i in 'jason')
# print(res)  # <generator object <genexpr> at 0x1130cf468>
# print(res.__next__())
"""生成器内部的代码只有在调用__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中,一个py文件就是一个模块,文件名为xxx.py模块名则是xxx,导入模块可以引用模块中已经写好的功能。如果把开发程序比喻成制造一台电脑,编写模块就像是在制造电脑的零部件,准备好零部件后,剩下的工作就是按照逻辑把它们组装到一起。
        将程序模块化会使得程序的组织结构清晰,维护起来更加方便,使用模块既保证了代码的重用性,又增强了程序的结构性和可维护性。

1、什么是模块?

  • 模块就是一系列功能的结合体 可以直接使用

2、为什么要用模块?

  • 极大地提升开发效率(拿来主义>>>:站在巨人的肩膀上)

3、模块的三种来源

        1)内置的模块
                无需下载 解释器自带 直接导入使用即可
        2)自定义模块
                自己写的代码 封装成模块 自己用或者发布到网上供别人使用
        3)第三方模块
                别人写的发布到网上的 可以下载使用的模块(很多牛逼的模块都是第三方)

4、模块的四种表现形式(大白话:长啥样子)

        1)使用python代码编写的py文件 # 掌握
        2)多个py文件组成的文件夹(包) # 掌握
        3)已被编译为共享库或DLL的c或C++扩展(了解)
        4)使用C编写并链接到python解释器的内置模块(了解)

六、模块的两种导入方式

  • 方式1:import…句式
    前提:在研究模块的时候 一定要分清楚谁是执行文件 谁是被导入文件(模块)
            模块简介.py是执行文件 md.py是被导入文件(模块)
    导入模块内部到底发送了什么事情
            1)执行当前文件 产生一个当前文件的名称空间
            2)执行import句式 导入模块文件(即执行模块文件代码产生模块文件的名称空间)
            3)在当前文件的名称空间中产生一个模块的名字 指向模块的名称空间
             4)通过该名字就可以使用到模块名称空间中的所有数据
            ps:相同的模块反复被导入只会执行一次
                    import md 有效
                    import md 无效(写了跟没写一样)
                    import md 无效(写了跟没写一样)

import句式的特点
        可以通过import后面的模块名点的方式 使用模块中所有的名字
        并且不会与当前名称空间中的名字冲突(指名道姓)

import md
money = 666
md.change()
print(money)
# def read1():
#     print('嘿嘿嘿')
# md.read2()
  • 方式2:from…import…句式

1)执行当前文件产生一个名称空间
2)执行导入语句 运行模块文件产生名称空间存放运行过程中的所有名字
3)将import后面的名字直接拿到当前执行文件中

"""
1.重复导入也只会导入一次
2.使用模块名称空间中的名字不需要加模块名前缀 直接使用即可
3.但是from...import的句式会产生名字冲突的问题
    在使用的时候 一定要避免名字冲突
4.使用from...import的句式 只能使用import后面出现的名字
    from...import...可以简单的翻译成中文
        从...里面拿...来用 没有提到的都不能用      指名道姓
"""
from md import name,money,read1
# print(name)  # jasonNB
# name = 'kevin'
# print(name)  # kevin

print(money)  # 报错  from md import name 只使用模块中的name名字
read1()

七、导入补充

1、可以给模块起别名(使用频率很高)

  • 比如模块名或者变量名很复杂 可以起别名简写
import md as m
print(m.name)
from md import name as n
print(n)

2、连续导入多个模块或者变量名

  • 连续导入多个模块 这多个模块最好有相似的功能部分 如果没有建议分开导入
  • 如果是同一个模块下的多个变量名无所谓!!!
import time, sys, md
from md import name, read1, read2
import time
import sys
import md

3、通用导入

from md import *
'''*表示md里面所有的名字   from...import的句式也可以导入所有的名字
如果模块文件中使用了__all__限制可以使用的名字  那么*号就会失效 依据__all__后面列举的名字
'''
print(name)
print(money)
举报

相关推荐

0 条评论