生成器 模块

今日内容概要

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

2.自定义range方法

3.生成器笔试题(了解)

4.生成器额外补充(了解)

5.模块简介

6.导入模块的两个方式

7.导入句式的补充说明

8.判断文件是模块还是脚本

9.循环导入问题

10.模块的查找顺序

 

 

今日内容详细

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

# 本质其实还是迭代器 只不过是我们自己通过写代码产生
也是有__iter__和__next__方法
def index():
   print('hello')
   yield 123
   print('zhou')
   yield 666
"""生成器对象也是节省存储空间的 特性与迭代器对象一致"""
"""当函数体代码中含有yield关键字
    第一次调用函数并不会执行函数体代码
    而是将函数变成了生成器
如何验证?
    是否有iter()和next()方法
"""
在没有被调用之前 就是一个普通的函数
print(index) # <function index...
加括号调用并接受结果:不执行代码 而是变成生成器对象(迭代器)
res = index()
print(res) # <generator object...
变成生成器对象之后调用__next__就会开始执行函数体代码
print(res.__next__()) # 123
yield有点像return的功能
print(res.__next__())
print(res.__next__())
print(res.__next__())
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 range(1,10):
   print(i)
先以两个参数的range方法为例
def my_range(start,end = None,step = 1):
  if not end: # 没有给end传值my_range(10)
       end = start
       start = 0
  while start < end:
       yield start
       start += step
# for i in my_range(1,100):
     print(i)
初步功能实现之后 再去考虑不同参数的情况
一个参数 三个参数
1. 针对一个参数情况
"""
end可以不传值 应该设置成默认参数
end = None
代码层面做判断 将形参数据做替换处理
  end = start
  start = 0
"""

yield关键字作用

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

def eat(name):
   print(f'{name}准备干饭')
   while True:
       food = yield
       print(f'{name}正在吃{food}')
res = eat('zhou')
# 想执行一次代码 如果想执行多次直至结束可以直接用for循环
res.__next__() # zhou准备干饭
res.__next__() # zhou正在吃None
res.send('肉') # zhou正在吃肉 这里可以给yield 传值并且自动调用一次__next__方法

生成器表达式

#也是为了节省存储空间
在后期我们做代码优化的时候 可以考虑使用 前期学习阶段可以忽略
res = (i for i in 'jason')
print(res) #<generator object...
print(res.__next__())
"""生成器内部的代码只有在调用__next__迭代取值的时候才会执行"""

#普通的求和函数
def add(n,i):
   return n + i
#生成器对象 返回1234
def test():
   for i in range(4):
       yield
#将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(n,i) for i in (add(10,i) for i in g))
  """
res = list(g) # list底层就是for循环相当于对g做了迭代取值操作
print(res)
  #### 诀窍就是抓n是多少

模块

python之所以很火并且适用于各行各业很大程度上的原因就是>>>:模块
   很多大佬写了很多非常牛逼的模块 供python工程师直接使用(白嫖)
   eg:
       import time 导入模块
       time.time() 调用方法
python刚开始出来的时候被很多其他语言的程序员看不起 嘲笑python是一个 调包侠(此时是贬义词)
但是当其他语言的程序员开始写python用到了模块之后发现'真香' 调包侠真好用 真牛逼 我好喜欢(此时是褒义词)
作为一名python工程师 如果遇到一个非常复杂的功能需要实现 那么第一时间不是想着如何去写 而是去网上找有没有相应的python模块!!!
以后出去工作了之后才应该考虑的
eg:人脸识别 语言转换 自动感应 类似更本摸不着头脑的几乎都有模块
           
1.什么是模块
模块就是一系列功能的结合体 可以直接使用
2.为什么要用模块
极大的提升开发效率
3.模块的三种来源
  1.内置的模块
   无需下载 解释器自带 直接导入使用即可
  2.自定义模块
   自己写的代码 封装成模块 自己用或者发布到网上供别人使用
  3.第三方模块
   别人写的发布到网上的 可以下载使用的模块(很多牛逼的模块都是第三方)
4.模块的四种表现形式
  1.使用python代码编写的py文件
  2.多个py文件组成的文件夹(包)
  3.已被编译为共享库或DDL的c或C++扩展
  4.使用C编写并链接到python解释器的内置模块

 

模块的两种导入方式

"""想要使用模块 必须先导入 而导入的方法有两种"""
方式1>>>:import...句式
   import 模块文件名
   print(模块文件名.name)
   模块文件名.函数名()
 

 

 


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

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

方式2>>>: from...import...句式
   from 模块文件名 import 模块里面的名字
1.执行当前文件产生一个名称空间
2.执行导入语句 运行模块文件产生名称空间存放运行过程中的所有名字
3.将import后面的名字直接拿到当前执行文件中
   
1.重复导入也只会导入一次
2.使用模块名称空间中的名字不需要加模块名前缀 直接使用即可
3.但是from...import的句式会产生名字冲突的问题
   在使用的时候 一定要避免名字冲突
4.使用from...import的句式 只能使用import后面出现的名字
   from...import...可以简单的翻译成中文
       从...里面拿...来用 没有提到的都不能用      指名道姓

补充说明

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)

 

 

 

 

 

posted @ 2022-03-24 16:50  顺溜_7  阅读(264)  评论(0编辑  收藏  举报