一、迭代器

li=[1,2,3]
f=li.__iter__()
print(f)
print(f.__next__())
print(f.__next__())
print(f.__next__()) #运行结果
<list_iterator object at 0x0000000000D770B8>
1
2
3

迭代器:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)

可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)

之前所说字符串、列表、元组、字典可迭代对象,其实是调用了__iter__方法,生成一个迭代器。

迭代器只能往前不会后退,且遍历取值时只能取一次。

for循环机制:

使用for循环对序列和字典进行迭代,其实就是调用数据对象的__iter__方法,生成迭代器,然后再调用__next__方法取值,直到捕捉StopIteration异常,以终止迭代。

二、生成器

1、定义:

  可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象

2、Python中生成器两种表现形式:

  生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

  生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

3、生成器优点:

  延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。

  节省内存

生成器的唯一注意事项就是:生成器只能遍历一次

4、生成器函数:

def lay_eggs(num):
for egg in range(num):
res='蛋%s' %egg
yield res
print('下完一个蛋') laomuji=lay_eggs()#我们拿到的是一只母鸡
print(laomuji)
laomuji.__next__() #蛋下完 母鸡就死了
def fun():
print('第一次')
res=yield
print('第二次',res)
yield
print('第三次') f=fun()
f.__next__()
f.send('fuck you') #一个效果跟next方法,另一个效果就是传递参数给上次yield

两个小例子:注意取值的地方

def test():
for i in range(4):
yield i g=test() g1=(i for i in g) #g1应该是一个新的生成器
g2=(i for i in g1) print(g)
print(g1)
print(g2)
print(list(g1)) #[0, 1, 2, 3]
print(list(g2)) #[] g2中的g1已经被上一步list取完,此处执行list没有值可取

有点绕的例子一

def add(n,i):
return n+i def test():
for i in range(4):
yield i g=test() #[0,1,2,3]
for n in [1,10]: # n=1 g=[1,2,3,4] ; n=10 g=[11,12,13,14]
g=(add(n,i) for i in g)
print('for',n,g) print(g)
print(list(g)) # [20, 21, 22, 23] 为什么是这个呢? # 过程:1、生成器g 2、for循环列表[1,10] 又是个生成器g-->覆盖之前的g 3、最终生成一个g=(add(10,))
# g=[0,1,2,3] => for循环 n=1 g=[1,2,3,4] ; n=10 g=[11,12,13,14]

比较绕的例子二

def add(n,i):
return n+i def test():
for i in range(4):
yield i g=test() #[0,1,2,3]
for n in [1,10]: # n=1 g=[1,2,3,4] ; n=10 g=[11,12,13,14]
g=(add(n,i) for i in g)
print('for',n,g) print(g)
print(list(g)) # [20, 21, 22, 23] 为什么是这个呢? # 过程:1、生成器g 2、for循环列表[1,10] 又是个生成器g-->覆盖之前的g 3、最终生成一个g=(add(10,))
# g=[0,1,2,3] => for循环 n=1 g=[1,2,3,4] ; n=10 g=[11,12,13,14]

例二的错误解析

def add(n,i):
return n+i def test():
for i in range(4):
yield i g=test() #代码执行,生成一个生成器 [0,1,2,3]
for n in [1,10]: #代码也执行 n= 1
g=(add(n,i) for i in g) # 第一次循环:全局变量n=1,生成新的生成器 g=((add(n,i) for i in test()))
#第二次循环:n=10,生成新的生成器 g=(add(n,i) for i in ((add(n,i) for i in test()))) # 代码执行到这里:全局变量 n = 10 # 如果对生成器 g 取值:执行 __next__() 方法 --> n =10,g=(add(n,i) for i in ((add(n,i) for i in test())))
# 类似于 递归
# print(list(g))

例二的正确解析姿势

最新文章

  1. xml Schema 基础
  2. PHP服务器配置环境变量
  3. pip安装
  4. 你真的了解UINavigationController吗?
  5. php中method_exists()和is_callable()如何进行语句判断
  6. 【转载】ogre内存管理
  7. IDEA配置maven
  8. log4j的简单应用(转载)
  9. ***用php的strpos() 函数判断字符串中是否包含某字符串的方法
  10. python:numpy(文件存取)
  11. 探讨socket引发SIGPIPE信号的问题
  12. (转)java并发之Executor
  13. 小程序 map组件问题 cover-view问题
  14. vue elementUI enter 回车 (转载)
  15. Linux 检查端口gps命令
  16. ubuntu16.04安装libzip库
  17. UVA506-System Dependencies(拓扑序)
  18. windows递归复制指定时间后修改过的文件
  19. 深入理解java虚拟机---虚拟机工具jstat(十七)
  20. SQL Server 如何添加删除外键、主键,以及更新自增属性

热门文章

  1. Composite C1是一个.Net平台上开源专业的CMS开源项目
  2. ajax简单后台交互
  3. 用docker cluster store实现kuryr的共享subnet
  4. 写给新手的WebAPI实践
  5. azkaben任务调度器
  6. jquery表格提交验证
  7. 【使用教程】论Windows下必备的抓包工具Fiddler2如何安装证书(查看Https)
  8. bzoj1588: [HNOI2002]营业额统计 splay瞎写
  9. Ubuntu16.04 server下配置MySQL,并开启远程连接
  10. VirtualBox 主机与虚拟机互通