生成器对象(自定义迭代器),自定义range方法,模块
自定义迭代器
一 、生成器与yield
'''
我们得到一个迭代器通常都是调用可迭代对象的__iter__方法 ,例如 list.iter() 得到一个迭代器,
但是当list很大时候,就违背了python的初衷,假设我们要创造一个包含1000w个值的可迭代对象,总不可能先把
这1000w个值放入列表,然后调用__iter__() 方法吧,太占内存 ,必须得提供一种机制打破python内置的产生
迭代器的方式 ,所以自定义迭代器应运而生,即生成器。
在Python中, 一边循环一边计算的机制, 称为生成器:generator, 若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象
'''
自定义range函数
def my_range(start,stop,step=1): # 自定义range函数
print('start...')
while start < stop:
yield start
start+=step
print('end...')
g=my_range(0,3)
print(g)
<generator object my_range at 0x01E2A808>
如何得到自定义的迭代器:
在函数内一旦存在yield关键字,调用函数并不会执行函数体代码
会返回一个生成器对象,生成器即自定义的迭代器
"""
如果函数体代码中含有多个yield关键字 执行一次__next__返回后面的值并且让代码停留在yield位置
再次执行__next__基于上次的位置继续往后执行到下一个yield关键字处
如果没有了 再执行也会报错 StopIteration
"""
生成器本身就是一个迭代器
print(g.__iter__) # <method-wrapper '__iter__' of generator object at 0x01AFB878>
print(g.__next__) # <method-wrapper '__next__' of generator object at 0x01AFB878>
'''生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器'''
用next(生成器)触发生成器所对应函数的执行
print(next(g)) # 触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
start...
0
print(next(g)) # 再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
1
print(next(g)) # 周而复始...
2
print(next(g)) # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
end...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
既然生成器对象属于迭代器,那么必然可以使用for循环迭代,如下:
for i in g:
print(i)
执行结果:
start...
0
1
2
end...
'''
有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于
return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
'''
yield关键字作用
yield最简单的解释
yield可以理解为一个return操作,但是和return又有很大的区别,执行完return,当前函数就终止了,
函数内部的所有数据,所占的内存空间,全部都没有了。而yield在返回数据的同时,还保存了当前的执行
内容,当你再一次调用这个函数时,他会找到你在此函数中的yield关键字,然后从yield的下一句开始执行。
例一
def num_print():
print('yield_1')
yield 'yield_1 return'
print('yield_2')
yield 'yield_2 return'
print('yield_3')
yield 'yield_3 return'
print('yield_4')
yield 'yield_4 return'
for i in num_print():
print('i:',i)
执行结果:
yield_1
i: yield_1 return
yield_2
i: yield_2 return
yield_3
i: yield_3 return
yield_4
i: yield_4 return
'''
上边在循环处一直在调用函数,可以看出每次调用函数,他会执行到yield进行返回,然后下一次调用时
他会从上一次执行yield的后边继续执行
'''
例二(可以接收外界的传值(了解))
def play():
while True:
game = yield
print(f'玩{game}')
res = play()
res.__next__()
res.send('LOL')
执行结果:
玩LOL
生成器表达式
语法
(返回值 for 元素 in 可迭代对象 if 条件)
返回一个生成器,生成器也是一个对象,属于中间值
g = (i ** 2 for i in range(5)) # 将使用生成器表达式得到的生成器对象赋给一个变量g
print(g)
'''输出:
<generator object <genexpr> at 0x109835b10>
'''
print(g.__next__())
"""生成器内部的代码只有在调用__next__迭代取值的时候才会执行"""
主要功能是,代码优化,节省存储空间。
生成器表达式和列表生成式的区别
模块
简介
在Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在
Python中要调用sqrt函数,必须用import关键字引入math这个模块
说的通俗点:模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块
模块的来源
目前有3个来源
1.内置的模块
无需下载 解释器自带 直接导入使用即可
2.自定义模块
自己写的代码 封装成模块 自己用或者发布到网上供别人使用
3.第三方模块
别人写的发布到网上的 可以下载使用的模块(很多牛逼的模块都是第三方)
导入模块的方法
第一种:import
在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用
import math来引入。
当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。
在调用math模块中的函数时,必须这样引用:
模块名.函数名
这种方式必须加上模块名调用,因为可能存在这样一种情况:在多个模块中含有相同名称的函数,此时如
果只是通过函数名来调用,解释器无法知道到底要调用哪个函数。所以如果像上述这样引入模块的时候,调用
函数必须加上模块名。
有时候我们只需要用到模块中的某个函数,只需要引入该函数即可,此时可以用下面方法实现:
from模块名import函数名1,函数名2....
'''
通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同
名称函数的时候,后面一次引入会覆盖前一次引入。也就是说假如模块A中有函数function( ),在模块B中也
有函数function( ),如果引入A中的function在先、B中的function在后,那么当调用function函数的时
候,是去执行模块B中的function函数。
'''
如果想一次性引入math中所有的东西,还可以通过from math import *来实现
第二种:from…import
Python的from语句让你从模块中导入一个指定的部分到当前命名空间中
语法如下:
from 模块名 import name,func1,func2(需要导入的函数或者变量)
例如,要导入模块fib的fibonacci函数,使用如下语句:
from fib import fibonacci
注意:
不会把整个fib模块导入到当前的命名空间中,它只会将fib里的fibonacci单个引入
"""
1.重复导入也只会导入一次
2.使用模块名称空间中的名字不需要加模块名前缀 直接使用即可
3.但是from...import的句式会产生名字冲突的问题
在使用的时候 一定要避免名字冲突
4.使用from...import的句式 只能使用import后面出现的名字
from...import...可以简单的翻译成中文
从...里面拿...来用 没有提到的都不能用 指名道姓
"""
补充
导入模块起别名,导入模块是对模块进行重命名,也就是给模块起一个别名。
import 模块名 as mod
'''
在后续使用时就可以使用这个别名
比如模块名或者变量名很复杂 可以起别名简写
'''
from 模块名 import *
'''
*表示md里面所有的名字 from...import的句 式也可以导入所有的名字
如果模块文件中使用了__all__限制可以使用的名字 那么*号就会失效 依据__all__后面列举的名字
'''
图文介绍两种导包
生成器对象(自定义迭代器),自定义range方法,模块的更多相关文章
- Python自动化--语言基础5--面向对象、迭代器、range和切片的区分
面向对象 一.面向对象代码示例: 1 class Test(): #类的定义 2 car = "buick" #类变量,定义在类里方法外,可被对象直接调用,具有全局效果 3 def ...
- python学习Day14 带参装饰器、可迭代对象、迭代器对象、for 迭代器工作原理、枚举对象、生成器
复习 函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.返回内部函数对象----> 延迟执行, 开放封闭原则: 功能可以拓展,但源代 ...
- day 13 迭代器、可迭代对象、迭代器对象、生成器、生成器对象、枚举对象
迭代器大概念 # 迭代器:循环反馈的容器(集合类型)# -- 不同于索引取值,但也可以循环的从容器对象中从前往后逐个返回内部的值# 优点:不依赖索引,完成取值# 缺点:不能计算长度,不能指定位取值( ...
- python之迭代器、可迭代对象、生成器、生成器对象、枚举类型
迭代器 # 迭代器:循环反馈的容器(集合类型)# -- 不同于索引取值,但也可以循环的从容器对象中从前往后逐个返回内部的值# 优点:不依赖索引,完成取值# 缺点:不能计算长度,不能指定位取值(只能从 ...
- ECMAScript 2015 迭代器协议:实现自定义迭代器
迭代器协议定义了一种标准的方式来产生一个有限或无限序列的值,并且当所有的值都已经被迭代后,就会有一个默认的返回值. 当一个对象只有满足下述条件才会被认为是一个迭代器:它实现了一个 next() 的方法 ...
- python14 1.带参装饰器 | wrapper 了了解 # 2.迭代器 ***** # 可迭代对象 # 迭代器对象 # for迭代器 # 枚举对象
## 复习 '''函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行 开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变 ...
- day14带参装饰器,迭代器,可迭代对象 , 迭代器对象 ,for迭代器 , 枚举对象
复习 ''' 函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行 开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变 装饰 ...
- Two---python循环语句/迭代器生成器/yield与return/自定义函数与匿名函数/参数传递
python基础02 条件控制 python条件语句是通过一条或多条语句的执行结果(Ture或者False)来执行的代码块 python中用elif代替了else if,所以if语句的关键字为:if- ...
- Python 3.x自定义迭代器对象
Python 3.x与Python 2.x之间存在着较多的语法细节差异.今天在看Python核心编程的时候,说到了自定义迭代器对象.于是动手将源码打了一遍,原书代码如下: class AnyIter( ...
随机推荐
- 学习saltstack (七)
一.SaltStack概述 Salt,,一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯. salt底层采用动态的连接总线, ...
- Netty学习摘记 —— UDP广播事件
本文参考 本篇文章是对<Netty In Action>一书第十三章"使用UDP广播事件"的学习摘记,主要内容为广播应用程序的开发 消息POJO 我们将日志信息封装成名 ...
- python学习笔记(八)——文件操作
在 windows 系统下,我们通过 路径+文件名+扩展名的方式唯一标识一个文件,而在 Linux 系统下通过 路径+文件名唯一标识一个文件. 文件分类:文件主要可以分为文本文件和二进制文件,常见的如 ...
- css3中user-select的用法详解
css3中user-select的用法详解 user-select属性是css3新增的属性,用于设置用户是否能够选中文本.可用于除替换元素外的所有元素,以下是user-select的主要用法和注意事项 ...
- Codepen 每日精选(2018-4-16)
按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以打开原始页面. 内容切换的交互效果https://codepen.io/jcoulterde... 报价卡片的交互效果ht ...
- python-蒙特·卡罗法计算圆周率
[题目描述]蒙特·卡罗方法是一种通过概率来得到问题近似解的方法,在很多领域都有重要的应用,其中就包括圆周率近似值的计问题.假设有一块边长为2的正方形木板,上面画一个单位圆,然后随意往木板上扔飞镖,落点 ...
- java中 什么叫隐藏(Hide)? 最好给个例子
4.隐藏 技术核心和实例前面已经给出,这里只是给出大家对这种现象的一个定义而已,马克-to-win:子类重新定义一个与父类那里继承来的域变量完全相同的变量,称为域的隐藏.这里所谓隐藏是指子类拥有了 ...
- CSS简单样式练习(四)
运行效果: 源代码: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta char ...
- vue项目处理dpr和多屏幕适配问题
<!DOCTYPE html> <html style="font-size:37.5px"> <head> <meta charset= ...
- 时间盲注——AS别名让盲注不盲
用处 页面存在时间盲注,注入成功了,你啥也看不到. 这只是为了能够查看到注入后的结果 网站部分源代码 <?php $conn = mysqli_("127.0.0.1",&q ...