迭代器,生成器,yield,yield from理解
迭代器
说到迭代器就得想说可迭代对象Iterable,实现了__iter__()方法的对象都是可迭代对象,例如很多容器,list ,set, tuples。使用iter方法可以把一个可迭代对象变成迭代器
迭代器是实现了__next__()方法的可迭代对象,也就是说迭代器必须实现__iter__()和__next__()方法,迭代器可以调用next()放不断的迭代,在给定的范围中返回数据,超出范围抛出异常。
几个有趣的例子:
from itertools import count
counter = count(start=13)
next(counter)
13
next(counter)
14 无限序列只要你愿意可以一直迭代下去,然而你无法创建一个这么大的list是不是可以说的迭代器的优点呢
from itertools import cycle
colors = cycle(['red', 'white', 'blue'])
print next(colors)
# 'red'
print next(colors)
# 'white'
print next(colors)
# 'blue'
print next(colors)
# 'red' 无限循环序列
from itertools import islice,cycle
colors = cycle(['red', 'white', 'blue'])
limited = islice(colors, 0, 6)
for x in limited:
print(x)
#有限序列
from itertools import islice
class Fib:
def __init__(self):
self.prev = 0
self.curr = 1
def __iter__(self):
return self def __next__(self): #注意在python2中需要写成next() python3中写成__next__()
value = self.curr
self.curr += self.prev
self.prev = value
return value
f = Fib()
print(list(islice(f, 0, 10)))
生成器
简单的生成器(x for x in range(5)) 和列表生成式很像,如果生成的逻辑比较复杂,用类似列表生成式的方式难以表达,我们可以用函数加关键字yield的方式。
在我的理解中,生成器generator是一种特殊的迭代器,他用yield来自动实现了__iter__()和__next__()方法
那我们用yield来实现一下斐波拉契:
def fib():
prev = 0
curr = 1
while True:
value = curr
yield value
curr += prev
prev = value
a = fib()
for x in range(10):
print(next(a))
yield
这个yield这么神奇吗?到底该怎么理解它呢?首先你可以把它当成一个return,之后就不再继续往下执行了,调用next()方法后继续执行,举个例子。
def foo():
print("starting...")
while True:
res = yield 4
print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(next(g))
starting...
4 # 走到yield 4的时候马上return 4(马上返回并没有赋值操作),
********************
res: None #接着 yield 继续往下走,进行赋值操作,4已经被return 出去了,所以res=None
4 # 进入下一个循环,又走到yield 4
我们稍微修改一下函数
def foo():
print("starting...")
while True:
res = yield 4
print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(g.send(7))
starting...
4
********************
res: 7 #挺神奇的怎么变成7了,注意我们此时用的是send()方法,它是传递了一个值给yield表达式,相当于res=7
4
yield from
yield 是从生成器里返回一个元素,那么yield from 从名字上理解就应该是返回一个生成器咯
def foo():
yield from [1,2,3] a = foo()
print(next(a))
print(next(a))
print(next(a))
结果:
1
2
3
是不是就可以理解为yield from 返回的是 iter([1,2,3])呢
下面看两个例子
def foo():
for i in range(5):
if i == 2:
return 'gg'
else:
yield i
a = foo()
for i in a:
print(i)
0
1
def foo():
for i in range(5):
if i == 2:
return 'gg'
else:
yield i
a = foo()
for i in range(5):
print(next(a))
0
1
StopIteration: gg
这是yield的特性,在使用for循环取遍历生成器的时候是不会触发StopIteration异常,使用next()可以触发,如果我们又想用for循环遍历又想触发异常怎么弄,再封装一下
def foo():
for i in range(5):
if i == 2:
return 'gg'
else:
yield i def fun(generator):
res = yield from generator
print(res) a = foo()
b = fun(a)
for x in b:
print(x)
0
1
gg # 捕捉到了异常并且把return 的值给了yield from 表达式
迭代器,生成器,yield,yield from理解的更多相关文章
- 【Python】迭代器、生成器、yield单线程异步并发实现详解
转自http://blog.itpub.net/29018063/viewspace-2079767 大家在学习python开发时可能经常对迭代器.生成器.yield关键字用法有所疑惑,在这篇文章将从 ...
- python迭代器与生成器及yield
一.迭代器(itertor) 1.可迭代: 在Python中如果一个对象有__iter__()方法或__getitem__()方法,则称这个对象是可迭代的(iterable). 其中__iter__( ...
- day4 内置函数 迭代器&生成器 yield总结 三元运算 闭包
内置函数: 内置函数 # abs()返回一个数字的绝对值.如果给出复数,返回值就是该复数的模. b = -100 print(b) print(abs(b)) # all() 所有为真才为真,只要有一 ...
- python基础-8迭代器(iter)和生成器(yield)
一 生成器 从Python2.2起,生成器提供了一种简洁的方式帮助返回列表元素的函数来完成简单和有效的代码. 它基于yield指令,允许停止函数并立即返回结果.此函数保存其执行上下文,如果需要,可立即 ...
- Python中的生成器与yield
对于python中的yield有些疑惑,然后在StackOverflow上看到了一篇回答,所以搬运过来了,英文好的直接看原文吧. 可迭代对象 当你创建一个列表的时候,你可以一个接一个地读取其中的项.一 ...
- Python迭代和解析(5):搞懂生成器和yield机制
解析.迭代和生成系列文章:https://www.cnblogs.com/f-ck-need-u/p/9832640.html 何为生成器 生成器的wiki页:https://en.wikipedia ...
- PHP的生成器、yield和协程
虽然之前就接触了PHP的yield关键字和与之对应的生成器,但是一直没有场景去使用它,就一直没有对它上心的研究.不过公司的框架是基于php的协程实现,觉得有必要深入的瞅瞅了. 由于之前对于生成器接触不 ...
- 关于生成器---(yield)
生成器:是自定义的迭代器(自己用python代码写的迭代器),函数中见到yield的就是生成器 那么yield前后的变量又该怎么理解 看例子一 def counter(name): print('%s ...
- Python中生成器和yield语句的用法详解
Python中生成器和yield语句的用法详解 在开始课程之前,我要求学生们填写一份调查表,这个调查表反映了它们对Python中一些概念的理解情况.一些话题("if/else控制流" ...
随机推荐
- 2019 SCUT SE 新生训练第四波 L - Boxes in a Line——双向链表
先上一波题目 https://vjudge.net/contest/338760#problem/L 这道题我们维护一个双向链表 操作1 2 3 都是双向链表的基本操作 4操作考虑到手动将链表反转时间 ...
- 洛谷 P1462 通往奥格瑞玛的道路——二分+spfa
上一波链接 https://www.luogu.org/problem/P1462 这道题我们考虑二分答案 然后每次跑一次spfa判断是否能够到达n点 tips:在不考虑负权边的前提下我们写最短路最好 ...
- 插件化框架解读之android系统服务实现原理(五)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 一.系统服务提供方式 1.我们平时最常见的系统服务使用方式 Wi ...
- python-列表基本操作
本文讲解python列表的常用操作: 1.list函数,可以将任何序列作为list的参数 names=['lilei','tom','mackle','dongdong']print(list(nam ...
- HDU 4886 TIANKENG’s restaurant(Ⅱ) ( 暴力+hash )
TIANKENG’s restaurant(Ⅱ) Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 130107/65536 K (Ja ...
- C#设计模式:状态者模式(State Pattern)
一,什么是状态设计模式? 1,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 2,当一个对象的内部状态改变时允许改变其行为,这个对象看起来像是 ...
- WPF 的二维绘图(二)——几何图形Geometry
<本文转自同行> 在WPF的DrawingContext对象中,提供了基本的绘制椭圆和矩形的API:DrawEllipse和DrawRectangle.但是,这些是远远不够用的,我们在日常 ...
- Redis 设置权限密码,以及如何开启关闭设置
linux redis 设置密码: 在服务器上,这里以linux服务器为例,为redis配置密码. 1.第一种方式 (当前这种linux配置redis密码的方法是一种临时的,如果redis重启之后 ...
- 2018-8-10-WPF-判断USB插拔
title author date CreateTime categories WPF 判断USB插拔 lindexi 2018-08-10 19:16:53 +0800 2018-8-5 13:0: ...
- phpredis中incr以及decr等自增命令出现的问题
在做项目中使用redis的incr以及hincrby自增时,出现自增失败,set之后的数据,无法自增,当redis中不存在该key时,直接用incr是成功的.查找了原因,是因为phpredis初始化的 ...