模块简介

今日内容概要

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

  • 自定义range方法

  • 生成器额外补充

  • 模块简介

  • 导入模块的两种方式

     

今日内容详细

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

# 本质其实还是迭代器 只不过是我们自己通过写代码产生
    也是有__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>
# print(next(res)) #123 只有在调用next才会执行函数体代码
# print(next(res)) # 666
# print(next()) # TypeError: next expected at least 1 arguments, got 0 取完之后也会报错
for i in res:
   print(i)
如果函数体代码中含有多个yield关键字 执行一次__next__返回后面的值并且让代码停留在yield位置
再次执行__next__基于上次的位置继续往下执行到下一个yield关键字处
如果没有了 再执行也会报错 StopIteration
   

二、自定义range方法

# range方法其实是一个可迭代对象
# for i in range(1,10):
#   print(i)
""""""
需求:通过生成器模拟range方法
def my_range():
   pass
for i in my_range(1,10):
   print(i)
   
# 1.先以两个参数的range方法为例
def my_range(start,end)
while start < end:
   yield start
   start += 1
for i in my_range(1,100):
   print(i)
2.一个参数的方法
def my_range(start,end=None)
if not end:
  end = start
  start = 0
   while start < end:
       yield start
       start += 1
for i in my_range(1,100)
   print(i)
3.三个参数的方法
def my_rnage(start,end,step)
while start < end:
       yield start
       start += step
for i in my_range(1,100):
   print(i)
# 写代码得时候先把初步功能实现之后 再去考虑不同参数的情况
""""""
end可以不传值 应该设置成默认参数 end=None
代码层面做判断 将形参数据做替换处理
    end = start
    start = 0
""""""
# for i in my_range(100):
# print(i)
# 这对三个参数情况
""""""
给函数添加第三个形参 并且设置成默认参数 默认值是1 step = 1
   每次递增的时候只需要递增step的数值即可
   start += step
''''''
for i in my_range(10)
print(i)


三、yield关键字作用

# 1.在函数体代码中出现 可以将函数变成生成器
# 2.在执行过程中 可以将后面的值返回出去 类似于return
# 3.还可以暂停代码的运行
# 4.还可以接收外界的传值

def eat(name):
   print(f'{name}准备干饭')
   while True:
       food =yield
       print(f'{name}正在吃{food}')
res = eat('老赵')
# 想执行一次代码 如果想之心多次直至结束 可以直接用for循环 next(res)
# next(res)   # 老赵正在吃None
# next(res)   # 老赵正在吃None

res.send('生日蛋糕')  # 可以给yield传值 并且自动调用一次next()
res.send('大鸭腿')  # 可以给yield 传值 并且自动调用一次next()

四、生成器表达器

# 也是为了节省存储空间
  在后期我们做代码优化的时候 可以考虑使用 前期学习阶段可以忽略
 
# res =(i for in 'jason')
# print(res) # <generator object <genexpr> at
# print(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工程师CV大法都要比其他工程师练得更加炉火纯青才行
如果遇到一个非常复杂的功能需要去实现 那么我们第一时间不是想着如何去写 而是去网上找有没有相应的python模块!!
   这是以后工作后才应该考虑的
# 1.什么是模块?
  模块就是一系列功能的结合体 可以直接使用
# 2.为什么要用模块?
   极大地提升开发效率(因为是拿来主义>>>站在巨人的肩膀上)
# 3.模块的三种来源
   1.内置的模块
   无需下载 解释器自带 直接导入使用即可
   2.自定义模块
   自己写的代码 封装成模块 自己用或者发布到网上工别人使用
   3.第三方模块
  别人写的发布在网上 可以下载使用的模块(很多牛逼的模块都是第三方写的)
# 4.模块的四种表现形式(长啥样子)
1.使用python代码编写的py文件
2.多个py文件组成的文件夹(包)
3.已被编译成共享库或DLL的或c或c++扩展
4.使用c编写并链接到python解释器的内置模块

 

 

六、模块的两种导入方式

"''"要想使用模块 必须先导入 而导入的方法有两种""""""
# 方式1>>>:import句式     md文内有name money read1
# import md
# print(md.name)
# md.read1()
""""""
前提:在研究模块的时候 一定要分清楚谁是执行文件 谁是被导入文件(模块)
    模块简介.py是执行文件  md.py是被导入文件(模块)  导入模块内部到底发生了什么事情呢?
   1.执行当前文件 产生一个当前文件的名称空间
   2.执行import句式 导入模块文件(即执行模块文件代码产生模块文件的名称空间)
   3.在当前文件的名称空间中产生一个模块的名字 指向模块的名称空间
   4.通过该名字就可以使用到模块名称空间中的所有数据  注意:相同的模块反复被导入只会执行一次
   比如:
   import md  有效
   import md  无效(写了跟没写一样)
   import md  无效(写了跟没写一样)
   
# name ='kevin'
# print(md.name) # jasonNB 获取模块中名称空间中的name
# print(name) # kevin 获取当前名称空间中的name
""""""
import句式的特点
  可以通过import后面的模块名点的方式 使用模块中所有的名字
   并且不会与当前名称空间中的名字冲突(指名道姓)
   """"""
   import md
   money = 666
   md.change() # 它修改的md文件中的值
   print(money)   # 666
   # def read1():
  print('嘿嘿嘿')
   # md.read2()
   
# 方式二>>>>: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.执行当前文件产生一个名称空间
2.执行导入语句 运行模块文件产生名称空间存放运行过程中的所有名字
3.将import后面的名字直接拿到当前执行文件中


导入模块方式二:from....import....  从什么中取什么
特征:
1.重复导入也只会导入一次
2.使用模块名称空间中的名字不需要加模块加点缀 直接使用即可
3.但是from...import的句式会产生名字冲突的问题
   在使用的时候 一定要避免名字冲突
4.使用from....import的句式 只能使用import后面出现的名字
from....import....可以简单的翻译成中文
从.....里面拿.....来用 没有提到的都不能用 指名道姓

 

 

七、导入补充

# 1.可以给模块起别名(使用频率很高)
''''''比如模块名或变量名很复杂 可以起别名简写
# import md as mdddd
# print(mdddd.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)

 

posted @ 2022-03-24 17:44  一颗平凡的小石头  阅读(58)  评论(0)    收藏  举报