python_魔法方法(六):迭代器和生成器
迭代器
自始至终,都有一个概念一直在用,但是我们却没来都没有人在的深入剖析它。这个概念就是迭代。
迭代的意思有点类似循环,每一次的重复的过程被称为迭代的过程,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。提供迭代方法的容器称为迭代器,通常接触的迭代器有序列(列表、元组、字符串)还有字典也是迭代器,都支持迭代的操作。举个列子,通常使用for循环进行迭代。
>>> for i in "python":
print(i) 打印结果
p
y
t
h
o
n
字符串就是一个容器,同时也是一个迭代器,for语句的作用就是触发这个迭代器的迭代功能,每次从容器里面依次拿出一个数据就,这就是迭代操作。
字典和文件也是支持迭代操作的:
>>> list1 = {"python":"python3.x",\
"go":"go是一种语言语法",\
"int":"python关键字",\
}
>>> for i in list1:
print("%s --> %s"%(i,list1[j]))
>>> for i in list1:
print("%s --> %s"%(i,list1[i]))
打印结果;
python --> python3.x
go --> go是一种语言语法
int --> python关键字
关于迭代,python还提供了两个BIF:iter() next()
对一个容器对象调用iter()就得到它的迭代器,调用next()迭代器就会返回下一个值,然后怎么结束了?如果迭代器没有值可以返回,python将抛出一个叫做Stoplteration的异常。
>>> string = "python"
>>> it = iter(string)
>>> next(it)
'p'
>>> next(it)
'y'
>>> next(it)
't'
>>> next(it)
'h'
>>> next(it)
'o'
>>> next(it)
'n'
>>> next(it)
Traceback (most recent call last):
File "<pyshell#26>", line , in <module>
next(it)
StopIteration
所以,利用这两个BIF,可以分析出for语句其实就是这么工作的:
>>> string = "python"
>>> it = iter(string)
>>> while True:
try:
each = next(it)
except StopIteration:
break
print(each) p
y
t
h
o
n
那么实现迭代器的魔法方法就有两个:__iter__() __next__()
一个容器如果是迭代器,就必须实现__iter__()方法,这个方法实际上就是返回迭代器本身。接下来就是重点实现的是__next__()魔法方法,因为他决定了迭代器的规则,看一段例子:
>>> class Fibs():
def __init__(self):
self.a =
self.b =
def __iter__(self):
return self
def __next__(self):
self.a,self.b = self.b,self.a+self.b
return self.a >>> fibs = Fibs()
>>> for i in fibs:
if i < :
print(i)
else:
break
这个迭代器的唯一亮点就是没有终点,所以如果没有跳出循环,它会不断迭代下去。那么就可以加一个参数,用于控制迭代的范围。
>>> class Fibs():
def __init__(self,n = ):
self.a =
self.b =
self.n = n
def __iter__(self):
return self
def __next__(self):
self.a,self.b = self.b,self.a+self.b
if self.a > self.n:
raise StopIteration
return self.a >>> fibs = Fibs()
>>> for i in fibs:
print(i)
生成器
前面是迭代器,下面来说生成器
生成器其实就是迭代器的一种实现,那既然迭代器就可以实现,为何还要生成器了?生成器之所以存在就是为了是python更为简洁,因为迭代器需要我们自己去定义一个类和实现相关的方法,而生成器则需要在普通函数中加一个yield语句即可。
生成器的发明,使python模仿协同程序的概念得以实现,所谓协同程序,就是可以运行的独立函数调用,函数可以暂停或者挂起,并需要的时候从程序离开的地方继续或重新开始。
对于调用一个普通的python函数,一般是从函数的第一行代码开始执行,结束与return语句,异常或函数所有语句执行完毕,一但函数将控制权交给调用者,就意味着全部结束。函数中做的所有工作以及保存在局部变量中的数据将丢失。再次调用这个函数时一切都将从头创建。
python是通过生成器来实现类似于协同程序的概念:生成器可以暂时挂起函数,并保留函数的局部变量等数据,然后在再次调用他的时候,从上次暂停的位置继续执行下去。
举个例子:
>>> def myGen():
print("生成器被执行!")
yield
yield >>> myG = myGen()
>>> next(myG)
生成器被执行! >>> next(myG) >>> next(myG)
Traceback (most recent call last):
File "<pyshell#76>", line , in <module>
next(myG)
StopIteration
通过例子,当函数结束的时候,一个StopIteration异常就会被抛出。由于Python的for循环会自动调用next()方法和处理StopIteration异常,所以for循环当然也是可以对生成器产生作用的:
>>> def myGen():
print("生成器被执行!")
yield
yield >>> myG = myGen()
>>> for i in myG:
print(i) 生成器被执行!
前面说的斐波那契数列例子,也可以用生成器实现:
>>> def fibs():
a,b = ,
while True:
a,b = b,a+b
yield a >>> for i in fibs():
if i>:
break
print(i)
写到现在,可以很好的用类别推导式了,哈哈,先来看下下面的什么意思吧
>>> a = [i for i in range() if not (i%) and i%]
>>> print(a)
[, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ]
含义很简单的,打印100以内能被2整除,不能被3整除
>>> b = {i:i%== for i in range()}
>>> b
{: True, : False, : True, : False, : True, : False, : True, : False, : True, : False}
还有集合推导式:
>>> c = {i for i in [,,,,,,,,,,,,,]}
>>> c
{, , , , , , , }
那么有没有字符串推导式,来验证下
>>> d = "I love python!"
>>> d
'I love python!'
看吧,不对吧,打印的是整个包含在字符串中的,所以不存在字符串推导式的说法,那元组了?
>>> e = (i for i in range())
>>> e
<generator object <genexpr> at 0x0000000003031360>
看打印出来的信息是generator,这就是生成器,用小括号括起来的正是生成器,来看下效果
>>> next(e) >>> next(e) >>> next(e) >>> next(e) >>> next(e) >>> next(e)
5
>>> next(e)
6
>>> next(e)
7
用for循环吧剩下的打印出来
>>> for i in e:
print(i)
生成器推导式如果作为函数的参数,可以直接写推导式,而不用加小括号(这个很牛气吧)。
>>> sum(i for i in range() if i%)
python_魔法方法(六):迭代器和生成器的更多相关文章
- 零基础学习python_魔法方法(41-48课)(迭代器)
接下来这个为啥要叫魔法方法呢,额,这个嘛我是跟小甲鱼的视频取的名字一样的,因为会讲比较多杂的东西,有... 魔法方法详细阅读地址:http://bbs.fishc.com/thread-48793-1 ...
- Python学习笔记:06魔法方法和迭代器
魔法方法,属性和迭代器 新式类 通过赋值语句__metaclass=true或者class NewStyle(object)继承内建类object,可以表明是新式类. 构造方法 对象被创建后,会立即调 ...
- Python笔记(二十八)_魔法方法_迭代器
迭代器用于遍历容器中的数据,但它不是容器,它是一个实现了__next__方法的对象 与迭代器相关的内置函数: iter(): 将一个对象转换成一个迭代器 next(): 访问迭代器中的下一个变量,直到 ...
- python_魔法方法(五):描述符和定制序列
描述符(property的原理) 描述符(descripto),用一句话来解释,描述符就是某种特殊的类的实例指派给另一个类的属性.那么什么是特殊类型的类呢?就是至少要在这个类中定义__get__(). ...
- python_魔法方法(四):属性访问
通常可以通过点(.)操作符的形式去访问对象的属性,也可以通过BIF适当地去访问属性,看个例子吧 >>> class A(): def __init__(self): self.x = ...
- python_魔法方法(三):__str__()和__repr__()
使用python的魔法方法和time模块定制一个计时器的类 1.用time模块里的localtime()方法获取时间2.time.localtime返回struct_time格式3.表现你的类:__s ...
- python_魔法方法(二):算术运算
python2.2之后,对类和类型做了同意,将int().float().str().list().touple()这些BIF转换为工厂函数 >>> type(len) <cl ...
- python_魔法方法(一):构造和析构
魔法方法总是被双下划线包围,例如:__init__() 魔法方法是面向对象的python的一切,它的魔力体现在总能在合适的时候调用. 先来介绍析构和构造的三个魔法方法: __init__():构造方法 ...
- Python_装饰器、迭代器、生成器
一.装饰器 装饰器的存在是为了实现开放封闭原则: 封闭: 已实现的功能代码块不应该被修改: 开放: 对现有功能的扩展开放. 理解装饰器的三要素: 函数的作用域 高阶函数 闭包 1. 闭包 闭包定义:如 ...
随机推荐
- vue 常见的新增、编辑、查看公用同一个页面
用vue开发经常会碰到,一个功能的新增.编辑.查看公用同一个页面,如果是页面暂且不提. 但是弹框,很多人会发现,如果是点击编辑,取消,再点新增,弹框上面是会有残留数据的,为什么会这样呢,因为在点编辑的 ...
- VBScript 内置函数
本页列出了所有内建的 VBScript 函数: Date/Time 函数 Conversion 函数 Format 函数 Math 函数 Array 函数 String 函数 其他函数 Date/Ti ...
- maven的配置文件取不同版本
1. 两个地方需要配置首先是要定义配置源,dev/test/prod对应的配置源需要指定:这是灵活的,可变的:其次要定义配置文件,该配置文件里面的内容采用占位符的方式来编制,在编译打包的过程中要动态根 ...
- 如何在开启了log-bin的MySQL Server中创建FUNCTION
在MySQL主从复制机器的master的数据库中创建function,报出如下错误: Error Code: 1418. This function has none of DETERMINISTIC ...
- MySQL数据库服务器参数优化mycnf,16G内存8核CPU,
业务场景: 后台支持手机在线更新系统,db服务器内存16G,8核,dell的pc服务器. qps: 200个左右 tps: 1个左右 一分钟50几个 sort_buffer_size = 32M 大了 ...
- Poj_1004_FinancialManagement
一.Description Larry graduated this year and finally has a job. He's making a lot of money, but someh ...
- vijos1779国王游戏
描述 恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这n位大臣排成一排,国王站在队伍的最前面.排好队后, ...
- 修改initrd.img里ko文件的一个小tips
在经历以下步骤解开initrd.img文件之后: 若file initrd.img 指示initrd.img为gzip文件,则2: mv initrd.img initrd.gz gunzip -d ...
- centos7 中文乱码解决方法
centos7 中文乱码解决方法 标签(空格分隔): centos7 1.查看安装中文包: 查看系统是否安装中文语言包 (列出所有可用的公共语言环境的名称,包含有zh_CN) # locale -a ...
- java web基础知识
1)TCP三次握手 第一次握手:客户端A将标志位SYN置为1,随机产生一个值为seq=J(J的取值范围为=1234567)的数据包到服务器,客户端A进入SYN_SENT状态,等待服务端B确认: 第二次 ...