① python递归生成器问题
如果调用 flatten3([[1,2],3])的话
for sublist in nested:
for element in fatten(sublist):
yield element
sublist分别为[1,2]和3
递归调用 fattern([1,2])返回一个包含1,2的子生成器,for element in fatten返回1,2用yield语句将1,2放入父生成器中,有了yield父生成器中才会有子生成器中的值
递归调用 flatten(3) TypeError执行yield 3,返回一个包含3的子生成器,yield element,3才会包含在父生成中
② 关于python的递归生成器
加了点注释,自己看吧,下次不要用图片了,直接拷贝代码吧
#-*-coding:cp936-*-
defflatten(nested):
try:
#这里首先检查nested是否可迭代,不可迭代则抛出TypeError
forsublistinnested:
#可迭代,那么递归,检查sublist是否还可以迭代
forelementinflatten(sublist):
#这里的element必定不可迭代,已经完全展开,因此使用yield输出,返回上层
#如果sublist是不可迭代的,那么flatten(sublist)返回的生成器就只有一个数据,就是sublist
#yieldelement也相当于yieldsublist
#否则的话,flatten(sublist)返回的是展开的数据
yieldelement
exceptTypeError:
#nested不可迭代,直接返回上层即可
yieldnested
③ Python生成器,递归时代码执行顺序
生成器就是用来生成有规律的值的
含有yield语句的函数就是生成器,counter(5)表示用参数start_at=5为初值调用生成
器,将函数对象赋值给count,count指向生成
器对象
每次调用生成器的next方法,就执行代码到yield语句处返回yield后的值,因此第一次调用
执行到yield返回
,下次调用
next时从上次执行处接着执行到yield语句处,所以生成器中可以用while
True语句不用担心死循环
yield这个表达式的值就是None,所以val一直是None
④ python递归生成器
defflattern(nested):
try:
iftype(nested)==type(""):
raiseTypeError()
forsublistinnested:
forelementinflattern(sublist):
yieldelement
exceptTypeError:
yieldnested
nested=[[1,2],[3,4],[5],6]
foriinflattern(nested):
printi
生成器的作用就是产生一个可迭代对象,可以在for这样的语句中使用,yield element语句的作用就是将element添加到这个可迭代对象
def flattern(nested):
try:
for sublist in nested:
for element in flattern(sublist): #迭代flattern(子列表)所产生的生成器
yield element #对flattern的递归调用只是生成了新的生成器,得将这些生成器中的值添加到当前生成器
except TypeError:
yield nested #如果变量nested不可迭代,for语句会出现TypeError错误,这时将nested添加到当前生成器中
在try开头加上了
if type(nested)==type(""):
raise TypeError()
因为字符是一直可以迭代的,如果不处理,如果参数中有字符串会无限递归下去
这个函数的作用就是将子列表完全扩展开产生一个生成器
⑤ python里yield的问题
'''
python中生成器是迭代器的一种,使用yield返回函数值。
每次调用yield会暂停,可以使用next()函数恢复生成器。
'''
deftest():
print('first')
yield1
print('second')
yield2
print('end')
r=test()
x=next(r)
print(x)
x=next(r)
print(x)
x=next(r)
print(x)
⑥ python的关键字yield有什么作用
yield是python中定义为生成器函数,其本质是封装了 __iter__和__next__方法 的迭代器;
与return返回的区别:return只能返回一次值,函数就终止了,而yield能多次返回值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行;
以下用示例说明:
deftest(a,b):
print("fromtest(),a+b=%d"%(a+b))
return("我是return返回的")
deftest_yield(a,b): #函数体中有yield关键字,函数就可以称为生成器函数
print("fromtest_yield,a+b=%d"%(a+b))
yield("我是第一次碰到yield关键字返回的") #程序运行时碰到yield,退出函数体并记录位置,下次调用跳过之前运行的代码
print("fromtest_yield,a*2=%d"%(a*2))
yield("我是第二次调用碰到yield关键字返回的")
print(test(11,33))
g=test_yield(11,33)
print(next(g)) #通过next()调用生成器函数
print(next(g)) #第二次调用生成器函数
'''
执行结果:
fromtest(),a+b=44
我是return返回的
fromtest_yield,a+b=44
我是第一次碰到yield关键字返回的
fromtest_yield,a*2=22
我是第二次调用碰到yield关键字返回的
'''
⑦ python中return和yield怎么用的两个有什么区别
常看到别人使用或讨论yield语法,能搜到的中文解释却不多,今天决心搞定yield,把暂时的理解贴到这里.
搞定yield之前: 叠代器(iterator)
发现yield: 生成器(constructor)
使用yield: 递归调用
1. iterator
叠代器最简单例子应该是数组下标了,且看下面的c++代码:
int array[10];
for ( int i = 0; i < 10; i++ )
printf("%d ", array[i]);
叠代器工作在一个容器里(array[10]),它按一定顺序(i++)从容器里取出值(array[i])并进行操作(printf("%d ", array[i])。
上面的代码翻译成python:
array = [i for i in range(10)]
for i in array:
print i,
for i in array干了什么(别乱想)?首先,array作为一个list是个容器,其次list这个内建类型有默认的next行为,python发现这些之后采 取的秘密的没被各位看到的动作是:拿出array这丫容器的叠代器,从里面next一下把值给i供for循环主体处置,for把这个值print了。
现在的问题是数据可以做容器叠代,代码可以吗?
怎么不行,碗碟可以用来放菜,wk们不就联想出用nt盛吗,当然我们的yield不会那么yellow + bt
2. constructor
怎么把函数变成constructor? 在函数体里有yield就行了!
def gen():
print 'enter'
yield 1
print 'next'
yield 2
print 'next again'
for i in gen():
print i
各位!python看到gen函数里出现yield,知道可以用next了,问题是怎么对代码这个容器玩next?
从容器里拿到iterator的时候它还什么也不是,处在容器入口处,对于数组来说就是下标为-1的地方,对于函数来说就是函数入口嘛事没干,但是万事俱备就欠next。
开始for i in g,next让itreator爬行到yield语句存在的地方并返回值,
再次next就再爬到下一个yield语句存在的地方并返回值,依次这样直到函数返回(容器尽头)。
您一定看出来上面代码的输出是:
enter
1
next
2
next again
如果没看出来请不要往下看了免得反被yield搞定。
3. 使用yield
yield的代码叠代能力不但能打断函数执行还能记下断点处的数据,下次next书接上回,这正是递归函数需要的。
例如中序遍历二叉树:
(应该是David Mertz写的)
def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x
for n in inorder(tree)
print n
当然yield这种代码next的能力还可以用在其它方面,发现拍案的在贴咯。
⑧ 初学python,想问些关于yield等等的问题
关于yield,楼下kanchi240说的完全正确。我就不补充了。
想说的是。你这个用yield的函数的逻辑可能存在问题。入口参数nested是一个数组,函数里for sublist in nested被执行的时候,如果nested被改变就不合理,会产生一个异常,也许你设计的初衷就是如此。
defflatten(nested):
try:
forsublistinnested:
forelementinflatten(sublist):
yieldelement
exceptTypeError:
yieldnested
if__name__=="__main__":
forxinflatten(nested=[1,[2,[3]]]):
printx,type(x)
输出结果是
1<type 'int'>
2<type 'int'>
3<type 'int'>
你这个好象又是递归函数。分解一下步骤是这样子。
flatten(nested=[1,[2,[3]]])
sublist=1
for element in flatten(sublist):此处在子调用异常,输出1, 但是它被递归函数的循环再次yield。
下面依次类推。
我把程序修改了一下,可能看起来更清晰。
defflatten(nested,level=0):
try:
forsublistinnested:
print"sublist:",sublist,type(sublist)
forelementinflatten(sublist,level+1):
printlevel,"yield",element
yieldelement
exceptTypeError:
printlevel,'yieldtypeerror',nested,type(nested)
yieldnested
if__name__=="__main__":
forxinflatten(nested=[1,[2,[3]]]):
printx,type(x)
输出结果是
sublist: 1 <type 'int'>
1 yield type error 1 <type 'int'>
0 yield 1
1 <type 'int'>
sublist: [2, [3]] <type 'list'>
sublist: 2 <type 'int'>
2 yield type error 2 <type 'int'>
1 yield 2
0 yield 2
2 <type 'int'>
sublist: [3] <type 'list'>
sublist: 3 <type 'int'>
3 yield type error 3 <type 'int'>
2 yield 3
1 yield 3
0 yield 3
3 <type 'int'>