python学习-Day17
今日内容详细
生成器对象(自定义迭代器)
若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象
def index():
print('你还记得我吗?')
yield 123
# yield 123, 111
print('是不是忘记我了!!!')
yield 666
'''
当函数体代码中含有yield关键字
第一次调用函数并不会执行函数体代码
而是将函数变成了生成器
'''
本质其实还是迭代器 只不过是我们自己通过写代码产生
# 生成器内置也是有 __iter__ 和 __next__ 方法,所以生成器本身也是一个迭代器
# 生成器对象也是节省存储空间的 特性与迭代器对象一致
我们可以用 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循环迭代
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):
while start < end:
yield start
start += 1
res = my_range(1,10)
for i in res:
print(i)
针对一个参数情况
def my_range(start, end=None):
if not end: # 没有给end传值 my_range(100)
end = start
start = 0
while start < end:
yield start
start += 1
for i in my_range(100):
print(i)
"""
end可以不传值 应该设置成默认参数: end=None
代码层面做判断 将形参数据做替换处理
end = start
start = 0
"""
针对三个参数情况
def my_range(start, end, step=1):
while start < end:
yield start
start += step
res = my_range(1,10,2)
for i in res:
print(i)
"""
给函数添加第三个形参,并且设置成默认参数,默认值是1,即step=1
每次递增的时候只需要递增step的数值即可
start += step
"""
自定义的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(10):
print(i)
for i in my_range(1, 10):
print(i)
for i in my_range(1, 10, 2):
print(i)
yield关键字作用
作用:
# 1.在函数体代码中出现 可以将函数变成生成器
# 2.在执行过程中 可以将后面的值返回出去 类似于return
# 3.还可以暂停住代码的运行
# 4.还可以接收外界的传值(了解)
玩法
def eat(name):
print(f'{name}准备约会')
while True:
food = yield
print(f'{name}给我递了{food}')
res = eat('jojo') # 并不会执行代码,而是转换成生成器
# 想执行一次代码 如果想执行多次直至结束 可以直接用for循环
res.__next__()
# res.__next__() # jojo给我递了None
res.send('一束鲜花') # jojo给我递了一束鲜花
# send() 可以给yield传值 并且自动调用一次__next__方法
res.send('大钻戒') # jojo给我递了大钻戒
yield与return对比
yield:
1.可以返回值(支持多个并且组织成元组)
2.函数体代码遇到 yield 不会结束而是'停住'
3.yield可以保存函数的运行状态挂起函数,用来返回多次值
4.yield可以将函数变成生成器,并且还支持外界传值
return:
1.可以返回值(支持多个并且组织成元组)
2.函数体代码一旦遇到 return 就直接结束
生成器表达式
创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成()
列表生成式返回的是一个列表,生成器表达式返回的是一个生成器对象
# 列表生成式返回的是一个列表
l=[x*x for x in range(3)]
print(l)
# [0, 1, 4]
# 生成器表达式返回的是一个生成器对象
g=(x*x for x in range(3))
print(g)
# <generator object <genexpr> at 0x101be0ba0>
优点:
为了节省存储空间 (一次只产生一个值在内存中)
注*
'''生成器表达式内部的代码只有在迭代取值的时候才会执行'''
res = (i for i in 'jojo')
print(res) # <generator object <genexpr> at 0x000001B6E9D1C2B0>
print(res.__next__()) # j
"""生成器内部的代码只有在调用__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(n, i) for i in g))
"""
# print(g) # 10
res = list(g) # list底层就是for循环 相当于对g做了迭代取值操作
'''g = (add(10, i) for i in (add(10, i) for i in 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,导入模块可以引用模块中已经写好的功能。
# 程序中的模块可以被重复使用
eg:
import time # 导入模块
time.time() # 调用方法
什么是模块 ?
模块就是一系列功能的结合体 可以直接使用
为什么要用模块?
使用模块既保证了代码的重用性,又增强了程序的结构性和可维护性。
还可以导入使用内置或第三方模块提供的现成功能,这种“拿来主义”极大地提高了程序员的开发效率。
模块的三种来源
1.内置的模块
无需下载 解释器自带 直接导入使用即可
2.自定义模块
自己写的代码 封装成模块 自己用或者发布到网上供别人使用
3.第三方模块
别人写的发布到网上的 可以下载使用的模块(很多牛逼的模块都是第三方)
模块的四种表现形式
1.使用python代码编写的py文件 # 掌握
2.多个py文件组成的文件夹(包) # 掌握
3.已被编译为共享库或DLL的c或C++扩展 (了解)
4.使用C编写并链接到python解释器的内置模块 (了解)
模块的两种导入方式
要想使用模块 必须先导入 而导入的方法有两种
import...句式
#文件名:md.py
print('from the md.py')
money = 1000
name = 'jojo'
def read1():
print('md', money)
def read2():
print('md模块')
read1()
def change():
global money
money = 0
在研究模块的时候 一定要分清楚谁是执行文件 谁是被导入文件(模块)
#文件名:mok.py
import md #导入模块md
a=md.money #引用模块md中变量money的值赋值给当前名称空间中的名字a
md.read1() #调用模块md的read1函数
md.change() #调用模块md中的change函数
mok.py是执行文件 md.py是被导入文件(模块)
通过md.的方式可以使用到模块中的‘名字’和函数
导入模块内部到底发送了什么事情
'''
1.执行当前文件 产生一个当前文件的名称空间
2.执行import句式 导入模块文件(即执行模块文件代码产生模块文件的名称空间)
3.在当前文件的名称空间中产生一个模块的名字 指向模块的名称空间
4.通过该名字就可以使用到模块名称空间中的所有数据
ps:相同的模块反复被导入只会执行一次
import md 有效
import md 无效(写了跟没写一样)
import md 无效(写了跟没写一样)
'''
import句式的特点
可以通过import后面的模块名点的方式 使用模块中所有的名字
并且不会与当前名称空间中的名字冲突(指名道姓)
from...import...句式
from md import name,money,read1
# print(name) # jojo
# name = 'kevin'
# print(name) # kevin
print(name) # 报错 from md import name 只使用模块中的name名字
read1()
"""
1.执行当前文件产生一个名称空间
2.执行导入语句 运行模块文件产生名称空间存放运行过程中的所有名字
3.将import后面的名字直接拿到当前执行文件中
"""
from...import...句式的特点
1.重复导入也只会导入一次
2.使用模块名称空间中的名字不需要加模块名前缀 直接使用即可
3.但是from...import的句式会产生名字冲突的问题
在使用的时候 一定要避免名字冲突
4.使用from...import的句式 只能使用import后面出现的名字
from...import...可以简单的翻译成中文
从...里面拿...来用 没有提到的都不能用 必须指名道姓
导入补充
可以给模块起别名(使用频率很高)
'''比如模块名或者变量名很复杂 可以起别名简写'''
import md as m
print(m.name)
from md import name as n
print(n)
连续导入多个模块或者变量名
import time, sys, md
from md import name, read1, read2
"""
连续导入多个模块 这多个模块最好有相似的功能部分 如果没有建议分开导入
如果是同一个模块下的多个变量名则无所谓
"""
import time
import sys
import md
通用导入
from md import *
'''
*表示md里面所有的名字
from...import的句式也可以导入所有的名字
如果模块文件中使用了__all__限制可以使用的名字,那么*号就会失效,而是依据__all__后面列举的名字
'''
print(name)
print(money)
python学习-Day17的更多相关文章
- Python学习day17 迭代器&生成器
迭代器&生成器 1. 迭代器 1.1 迭代器 迭代:迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果.每一次对过程的重复称为一次"迭代" 迭代器:帮助对某种对象 ...
- Python学习-day17 jQuery method and demo
一:介绍: jQuery:是DOM和js的封装.jQuery是一个兼容多浏览器的javascript库,核心理念是write less,do more(写得更少,做得更多).现在大多数的pc端的网站都 ...
- python学习博客地址集合。。。
python学习博客地址集合... 老师讲课博客目录 http://www.bootcdn.cn/bootstrap/ bootstrap cdn在线地址 http://www.cnblogs. ...
- python学习之旅
python学习分类 python基础 +- day01——python初始.变量.常量.注释.基础数据类型.输入.if day02——while.字符串格式化.运算符.编码初识 day03—— ...
- Python学习--04条件控制与循环结构
Python学习--04条件控制与循环结构 条件控制 在Python程序中,用if语句实现条件控制. 语法格式: if <条件判断1>: <执行1> elif <条件判断 ...
- Python学习--01入门
Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...
- Python 学习小结
python 学习小结 python 简明教程 1.python 文件 #!/etc/bin/python #coding=utf-8 2.main()函数 if __name__ == '__mai ...
- Python学习路径及练手项目合集
Python学习路径及练手项目合集 https://zhuanlan.zhihu.com/p/23561159
- python学习笔记-python程序运行
小白初学python,写下自己的一些想法.大神请忽略. 安装python编辑器,并配置环境(见http://www.cnblogs.com/lynn-li/p/5885001.html中 python ...
随机推荐
- LCS&&LRC&&LIS问题
注:最近笔试题经常碰到DP动态规划的问题,但是由于本人没有接触过DP,笔试后看到别人家的答案简洁又漂亮,真的羡慕:难的DP自己可能不会,那再见到常见的LCS和LRS以及LIS为问题总该会吧: 资料参考 ...
- vue-router的原理,例如hashhistory和History interface?
vue-router用法:在router.js或者某一个路由分发页面配置path, name, component对应关系 每个按钮一个value, 在watch功能中使用this.$router.p ...
- 为什么Java中 wait 方法需要在 synchronized 的方法中调用?
另一个棘手的核心 Java 问题,wait 和 notify.它们是在有 synchronized 标记的方法或 synchronized 块中调用的,因为 wait 和 modify 需要监视对其上 ...
- Spring 的优点?
(1)spring属于低侵入式设计,代码的污染极低: (2)spring的DI机制将对象之间的依赖关系交由框架处理,减低组件的耦合性: (3)Spring提供了AOP技术,支持将一些通用任务,如安全. ...
- 用maven建立一个工程4
在命令行里面输入cd C:\Users\admin\Documents\hello 然后按回车 再输入这行代码 mvn archetype:generate -DgroupId=com.liyongz ...
- DRF 简单使用(详细注释版)
1.djangorestframework使用 下载安装 pip install djangorestframework ## djangorestframework pip install djan ...
- Altium Designer 原理图的绘制前导
元件库.封装库设计 部分元器件厂商或者经销商不提供元件库和封装库,只给了元器件尺寸图,所以需要自行设计元件库文件或是封装库文件 元件库设计: 新建 .SchLib 文件:File -> N ...
- Day10 - JS 实现 Checkbox 中按住 Shift 的多选功能
Day10 - JS 实现 Checkbox 中按住 Shift 的多选功能 作者:liyuechun 简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战.项目免费提供了 3 ...
- 初识JavaScript EventLoop
Event Loop指的是计算机系统的一种运行机制.JavaScript采用此机制解决单线程引发相关问题 在浏览器中的web应用会涉及到.JavaScript引擎.WebAPI.Event Loop. ...
- linux-RHEL7.0 —— 《Linux就该这么学》阅读笔记
目录 linux-RHEL7.0 安装部署 修改root密码 RPM(红帽软件包管理器) YUM(软件仓库) Systemd初始化进程 总结 linux命令 帮助命令 man 系统工作命令 echo ...