ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

py 生成器对象,yield,模块的学习 day 17

2022-03-24 23:57:09  阅读:183  来源: 互联网

标签:__ 迭代 17 res py 生成器 模块 print import


昨日内容回顾

可迭代对象

1.什么是迭代
	迭代就是更新换代,但是每次迭代的过程都需要依赖上一次的结果。最常见的例子就是:游戏的更新
    
2.可迭代对象
	内置有__iter__方法的都可以称之为是可迭代对象
    字符串、列表、字典、元组、集合、文件对象
'''
	1.__iter__类似代码的读法>>>:双下方法
	2.简便方法
	  __iter__  iter()
	  __next__  next()
'''

3.迭代器对象
# 1.迭代器对象的特征
	有__iter__和__next__方法
# 2.如何产生迭代器对象
	可迭代对象调用__iter__方法就会变成迭代器对象
    '''
    迭代器对象如果再次调用__iter__方法还是迭代器对象本身
    '''
# 3.迭代器对象的作用
	能够存储数据并节省存储空间,是一种优化的数据存储形式
# 4.迭代器对象取值的特征
	内部数据每取一次就会少一个,取完了内部数据也就空了(但是是同一个迭代器)
# 5.迭代器对象的主要应用
	提供了一种不依赖与索引取值的方式
    是对无序容器类型进行迭代取值的必要

异常处理

异常处理的语法结构:

try:
    	可能会出错的代码
  except 出错的类型1 as e:
    	针对出错类型的解决措施
  except 出错的类型2 as e:
    	针对出错类型的解决措施 
  except 出错的类型3 as e:
    	针对出错类型的解决措施
  except 万能异常(Exception) as e:
    	统一出错的解决措施
  else:
    	可能会出错的代码没有出错 执行完毕后就会走else
  finally:
    	无论上面怎么走 最后都要走finally

for循环的本质

res = 可迭代对象.__iter__()
while True:
    try:
        print(res.__next__)
    except StopIteration as e:
        break
# 万能异常可以捕获很多常见的异常类型

今日学习

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

# 本质上还是迭代器,只是通过自己写代码产生的
其中也是包含: __iter__和__next__方法的
例:
def index():
    print('are you kidding me ?')
    yield 123
    yield 123, 111
    print('must be forgot me')
    yield 666
    
'''生成器对象也是节省存储空间的 特性与迭代器对象一致'''
'''
	当函数体代码中含有yield关键字
    第一次调用函数并不会执行函数体代码
    而是将函数变成了生成器
'''

# 没有调用之前,它就是一个普通的函数
print(index)  # <function index at 0x00000269CC501F28>

# 加括号调用并接收结果:不执行代码,而是变成生成器对象(迭代器)
res = index()
print(rse)  
# <generator object index at 0x00000269CC992E08>
# 变成生成器对象之后调用__next__就会开始执行函数体代码
res.__next__()  # are you kidding me ?
print(res.__next__())  
# are you kidding me ?
# 123
print(res.__next__())  # 
# are you kidding me ?
# 123
# (123, 111)
print(res.__next__())
# are you kidding me ?
# 123
# (123, 111)
# must be forgot me
# 666
print(res.__next__())  # 生成器对象内容被取完
# 报错,因为没东西取了
# StopIteration
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)
    
# 首先以两个参数的range方法为例
def my_range(start, end=None, step=1):
    if not end:  # 没有给end传值  my_range(10)
        end = start
        start = 0
'end可以不传值,应该设置成默认参数,end=None'
'将形参进行调换 end = start'
    while start < end:
        yield start
        start += step
'第三个参数step默认值为1'
'每次递增就只用递增step的值就好了 start += step'     

# 先建大框架,然后再考虑参数的情况,整体状态如下
def my_range(start, end=None, step=1):
    if not end:
        end = start
        start = 0
    while start < end:
        yield start
        start += step
for i in my_range(1,10):
    print(i)  
'''
1
2
3
4
5
6
7
8
9
'''

yield关键字的作用

yield关键字有以下的作用:
1.在函数体代码中出现,可以将函数变成生成器
2.在执行的过程中可以将跟在yield后面的值返回出去,类似于return的返回作用
3.而且它还可以暂停住代码的运行
4.最后还有一个接收外界传值的作用

def eat(name):
    print(f'{name}可以吃饭了)
    while True:
          food = yield
          print(f'{name}正在吃什么{food})
res = eat('老赵')
# 想执行一次代码,用双下next方法,如果想多次执行可以用for循环
res.__next__()  # 老赵可以吃饭了
res.__next__()  # 老赵正在吃什么None
res.__next__()  # 老赵正在吃什么None
# 问,现在在food值为None的情况下如何传值呢
'send方法可以给yield传值,而且还能自动调用一次双下next方法'
res.send('蛋糕')  # 老赵正在吃什么蛋糕
res.send('烩面')  # 老赵正在吃什么烩面

生成式表达式

功能:为了节省存储空间
res = (i for i in 'jason')
print(res)  
# <generator object <genexpr> at 0x1130cf468>
print(res.__next__())
'生成器内部的代码只有在调用__next__迭代取值的时候才会执行'

# 普通的求和函数
def add(n, i):
    return n + i
# 再定义一个函数test
def test():
    for i in range(4):
        yield i
# 将test函数变成生成器对象
res = test()
# 一个for循环
for n in (1, 10):
    res = (add(n, i) for i in res)
"""
    第一次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)
res = [20, 21, 22, 23]

模块

'''
import time  # 导入模块
time.time()  # 调用模块内的方法
'''
# 1.什么是模块?
	模块就是某一特定功能方向的方法,可以直接调用使用
# 2.为什么要用模块?
	极大地提升开发效率,可以省去很多时间从而完成需求的功能
# 3.模块的三种来源
	1.内置的模块
  	无需下载,python解释器自带,直接导入使用即可
  2.自定义模块
  	自己写的符合某一功能的代码,封装成模块,自己用或者发布到网上供别人使用
  3.第三方模块
  	别人写的发布到网上的,可以下载使用的模块(很多大佬都是写第三方模块的)
# 4.模块的四种表现形式
  1.使用python代码编写的py文件  # 掌握
  2.多个py文件组成的文件夹(包)  # 掌握
  3.已被编译为共享库或DLL的c或C++扩展(了解)
  4.使用C编写并链接到python解释器的内置模块(了解)

模块的两张导入方式

导入的方法有两种:
# 方式一: import方式...句式
import xxx(你需要导入的模块的名称)
'首先必须明白谁是执行文件谁是被导入文件(模块)'
'''
模块中 .py是执行文件  md.py文件是被导入文件(模块)
模块只需要导入一次即可,不需要重复导入
'''
然而导入模块的内部发生了什么事呢?
	1.执行当前文件 产生一个当前文件的名称空间
    2.执行import句式 导入模块文件(即执行模块文件代码产生模块文件的名称空间)
    3.在当前文件的名称空间中产生一个模块的名字 指向模块的名称空间 
    4.通过该名字就可以使用到模块名称空间中的所有数据
ps:相同的模块反复被导入只会执行一次
    
print(md.name)  # 获取模块名称空间中的name
print(name)  # 获取当前名称空间中的name

import md
money = 666
md.change()
print(money)

# 方式二: from...import...句式
from md import name,money,read1
print(name)  # jasonNB
name = 'kevin'
print(name)  # kevin

print(money)  # 报错  from md import name 只使用模块中的name名字
read1()
'''
执行当前文件产生一个名称空间
执行导入语句,运行模块文件产生名称空间存放运行过程中的所有名称
将import后面的名字直接拿到当前执行文件中
'''

# 注意
1.模块即使重复导入也只能导入一次
2.模块空间名称空间中的名字不需要加模块名前缀,大可直接使用
3.但是from...import的句式会产生名字冲突的问题,所以使用的时候要注意
4.使用from...import的句式,只能使用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后面列举的名字

今日的两种模块导入方式的内部内部图

今天主要学习了模块的一些使用及方法,受益颇深,原来导入模块也有这么多讲究,着实要好好想想思考思考

标签:__,迭代,17,res,py,生成器,模块,print,import
来源: https://www.cnblogs.com/kazz/p/16052730.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有