python迭代器_python 迭代器

回归问题的本质,为什么要用yield而不是print

直接在 fab 函数中用 print 打印数字会导致该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列。

看看这个有什么区别

def item_iterator(embed_list):

for item in embed_list:

if isinstance(item, (tuple, list)):

# print(type(item_iterator(item)))

for item in item_iterator(item):

print(item)

else:

yield item

lst = (0, (1, 2), (3, (4, 5)))

for item in item_iterator(lst):

print("ok")

print("ok",item)

def item_iterator(embed_list):

for item in embed_list:

if isinstance(item, (tuple, list)):

# print(type(item_iterator(item)))

for item in item_iterator(item):

yield item

else:

yield item

lst = (0, (1, 2), (3, (4, 5)))

for item in item_iterator(lst):

print("ok")

print("ok",item)

区别很明显,print虽然可以输出,但是item_iterator是作为函数,而使用yield,item_iterator是作为迭代器,统一在for循环中,输出,更符合程序数据统一出口。简洁。

迭代器真是复杂。用pythontutor运行上面的例子,明白了中间那个for的作用。

写迭代,估计都要用到那个for。

基础概念

https://www.zhihu.com/question/20829330

http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html

如果还是不能理解,有很好的工具可以帮助调试。

http://pythontutor.com/visualize.html#mode=display

找到一篇好理解的文章

http://kissg.me/2016/04/09/python-generator-yield/

yield作为一个暂停恢复的点,代码从yield处恢复,又在下一个yield处暂停.可见,在一次next()(非首次)或send(value)调用过程中,实际上存在2个yield,一个作为恢复点的yield与一个作为暂停点的yield.因此,也就有2个yield表达式.send(value)方法是将值传给恢复点yield;调用next()表达式的值时,其恢复点yield的值总是为None,而将暂停点的yield表达式的值返回.为方便记忆,你可以将此处的恢复点记作当前的(current),而将暂停点记作下一次的(next),这样就与next()方法匹配起来啦.

iterators-generators-iterables.png可迭代对象(Iterable)是实现了__iter__()方法的对象,通过调用iter()方法可以获得一个迭代器(Iterator)

迭代器(Iterator)是实现了__iter__()和__next__()的对象

for ... in ...的迭代,实际是将可迭代对象转换成迭代器,再重复调用next()方法实现的

生成器(generator)是一个特殊的迭代器,它的实现更简单优雅.

yield是生成器实现__next__()方法的关键.它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回.yield迭代器理解顺序1.素数

def prime_sieve(n):

flags = [True] * n

flags[0] = flags[1] = False

for i in xrange(2, n):

if flags[i]:

yield i

for j in xrange(2, (n - 1) / i + 1):

flags[i * j] = False

for p in prime_sieve(100):

print p

2.两个yield + 循环

def item_iterator(embed_list):

for item in embed_list:

if isinstance(item, (tuple, list)):

item_iterator(item)

#当在第4行递归使用item_iterator(item)时,它并不是一个函数的递归调用,而是一个generator object

else:

yield item

lst = (0, (1, 2), (3, (4, 5)))

for item in item_iterator(lst):

print item

正确

def item_iterator(embed_list):

for item in embed_list:

if isinstance(item, (tuple, list)):

for i in item_iterator(item)

yield i

else:

yield item

3.next(it)

4.理解

对一个序列进行全排列

内部for-》外部for-》外部for

外部for循环,两次,你看

for i in range(len(li)):

li[0], li[i] = li[i], li[0]

如果li只要两个元素,那么会循环两次,[1,2]会变成[1,2]和[2,1]

例子

1.python 学习笔记 第二版

def framework(logic):

try:

it = logic()

s = next(it)

print "[FX] logic: ", s

print "[FX] do something"

it.send("async:" + s)

except StopIteration:

pass

def logic():

s = "mylogic2"

r = yield s

print r

print framework(logic)

def fibonacci():

a,b=0,1

while True:

yield b

a, b = b, a + b

fib=fibonacci()

print fib.next()

print fib.next()

print fib.next()

print [fib.next() for i in range(10)]

2.python 迭代器 生成器 - jihite

def fab(max):

n, a, b = 0, 0, 1

while n < max:

yield b

a, b = b, a + b

n = n = 1

for n in fab(5):

print n

a, b = b, a + b 赋值结果,a=b,b=a+b,引用的都是前面的值

>>> a = 1

>>> b = 2

>>> t = b, a + b

>>> t

(2, 3)

>>> a, b = t

>>> a

2

>>> b

3

注意t是一个tuple

def consumer(name):

print("%s 准备吃包子啦!" %name)

while True:

baozi = yield

print("包子[%s]来了,被[%s]吃了!" %(baozi,name))

c = consumer("alex")

c.next()

c.send("韭菜馅")

3.对一个序列进行全排列

def permutations(li):

if len(li) == 0:

yield li

else:

for i in range(len(li)):

li[0], li[i] = li[i], li[0]

for item in permutations(li[1:]):

#有for循环,就会输出yield内容

#[li[0]] + item+permutations(li[1:])

yield [li[0]] + item

for item in permutations(range(3)):

print item

怎么理解呢?

先外部,后全部内部#0 0返回的数据以及数据类型

# [1,2,3] 先执行第一个for循环

# 然后执行第二个for循环

# 变成[1,2],再执行一次第一个for循环,

#然后执行第二个for循环

#变成[2],#然后执行第二个for循环

#完成最后一层,退回到第一个for循环最新理解

从前到后,而不是从后到前

先执行外部for,然后内部for,如果内部for有很多个,那么内部for-》外部for-》外部for

这样的顺序

最后执行的话,item输出为none,然后变成0,1,2,0,2,1.

就是这样。

[0, 1, 2]

[0, 2, 1]

[1, 0, 2]

[1, 2, 0]

[2, 0, 1]

[2, 1, 0]

其实,还有这种for循环,可以用最小的个数来理解,比如2个。

了解下输出[0,1,2]和[0,2,1]的过程

1.[0,1,2]

li=[0,1,2] i=0

li=[1,2] i=0

li=[2] i=0

li empty list

li=[2] item empty list

return value 2

li=[1,2] item=[2] i=0

return [1,2]

li=[0,1,2] item=[1,2]

return [0,1,2]

2.[0,2,1]

li=[0,1,2] item=[1,2]

li=[1,2], item=[2] i=0

.............

li=[2,1] item=[2] i=1

li=[1]

li=[2,1],item=1

................

return [0,2,1]

可以看出li,到了li[1:]后,执行那个for循环语句,交互数值,这步出现了2个结果

然后外层循环是3个,所以结果是6种结果。

print(list(itertools.permutations(horses)))

参考https://my.oschina.net/passer007/blog/483681

Python Iteration,itertools(Python迭代器,itertool个人总结)

yield返回的值是什么

4.def addlist(alist):

for i in alist:

yield i + 1

print "next"

yield i + 2

##会输出两次,多个yield会输出多次

alist = [1, 2, 3, 4]

for x in addlist(alist):

print x,

5.def permutations(li):

if len(li) == 0:

yield li + [1]

else:

for i in range(len(li)):

li[0], li[i] = li[i], li[0]

for item in permutations(li[1:]):

yield [li[0]] + item + [9]

for item in permutations(range(3)):

print item

yield li,那么说明li已经是个迭代器了

for循环有几次就循环几次

yield li = yield []

6.next(it) it为函数,这就更加清楚了import time

def A():

while True:

print("----我是A函数---")

yield

time.sleep(0.5)

print("AAAAAAAAAAAA")

def B(c):

while True:

print("----我是B函数---")

next(c)

#next会不断从yield处暂停和恢复

time.sleep(0.5)

print("BBBBBBBBBBBB")

if __name__ == '__main__':

a = A()

B(a)

7.八皇后问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值