生成器:是自定义的迭代器(本身用python代码写的迭代器),函数中见到yield的就是生成器python
那么yield先后的变量又该怎么理解面试
看例子一app
def counter(name): print('%s ready to count'%name) num_list=[] while True: #这个语句的做用是循环利用yield,这样的话对象就能够无限传值了 #yield前的变量是接收值的
num=yield '如今的列表是%s'%num_list #yield后面的变量会打印处理
num_list.append(num) print('%s start to count %s'%(name,num)) e=counter('xincheng') print(e.send(None)) #或者 next(e)
print(e.send('1')) print(e.send('2')) for i in range(3,10): print(e.send(i))
例子一打印结果为:ide
xincheng ready to count 如今的列表是[] xincheng start to count 1 如今的列表是['1'] xincheng start to count 2 如今的列表是['1', '2'] xincheng start to count 3 如今的列表是['1', '2', 3] xincheng start to count 4 如今的列表是['1', '2', 3, 4] xincheng start to count 5 如今的列表是['1', '2', 3, 4, 5] xincheng start to count 6 如今的列表是['1', '2', 3, 4, 5, 6] xincheng start to count 7 如今的列表是['1', '2', 3, 4, 5, 6, 7] xincheng start to count 8 如今的列表是['1', '2', 3, 4, 5, 6, 7, 8] xincheng start to count 9 如今的列表是['1', '2', 3, 4, 5, 6, 7, 8, 9]
例子二:函数
def counter(name): print('%s ready to count'%name) num_list=[] while True: num=yield num_list,'hehe' #yield后面的变量会答应处理,多个用,隔开,结果就会放入一个元组中
num_list.append(num) print('%s start to count %s'%(name,num)) #yield后面的语句通常为下一个yield的开始
e=counter('xincheng') next(e) s=e.send('1') #xincheng start to count 1
print(s,type(s)) #(['1'], 'hehe') <class 'tuple'> yield后面的东西是给对象传的值,多个值放在一个元组中
例子三:yield from 能够从一些地方获取值spa
def gen1(): for c in 'ab': yield c for i in range(3): yield i print(list(gen1())) def gen2(): yield from 'ab'
yield from range(3) print(list(gen2())) #两个print的值都为['a', 'b', 0, 1, 2]
面试题一code
def demo(): for i in range(4): yield i g=demo() g1=(i for i in g) g2=(i for i in g1) print(list(g1)) #[0, 1, 2, 3]
print(list(g2)) #[]
#g是第一个生成器,g1取得值来自于g,g2取值来自于g1,归根到底仍是g,list是可迭代对象,将g1赋予list得方法,实际上是从g中取值,并且取完了,g2天然就是空值了
请看下面得变体
def demo():
for i in range(4):
yield i
g=demo()
g1=(i for i in g)
g2=(i for i in g1)
print(next(g)) # 0
print(next(g1)) # 1
print(next(g2)) # 2
面试题二:对象
def add(n,i): return n+i def test(): for i in range(4): yield i g=test() for n in [1,10]: g=(add(n,i) for i in g) print(list(g)) #此例子的for循环中有两个元素,其结果为 [20, 21, 22, 23]
#若是将for循环下面得表达式换成g=[add(n,i) for i in g] 换成了【】,结果为[11, 12, 13, 14]
#若是将for循环的表达式换成 for n in [1,3,10] 或者 for n in [1,11,10] 都是三个元素,其结果为[30, 31, 32, 33]
#若是是 for n in [1,3,6,7,10,11,100,10]总共8个元素 其结果为[80, 81, 82, 83]
面试二总结:生成器的特色是惰性机制,也就是说你找它要,它才会给你值blog
在上一题的for循环中,无论你循环多少次,生成器的取值都是列表【】中的最后一个值内存
g在取值前,是一个内存地址,for循环一直改变着g的内存地址,最后是n=10的内存地址
for循环一次,g中的值就加一次,每次加的都是n=10的内存地址的值
for循环第一次: 10+0 10+1 10+2 10+3
for循环第二次:10+10+0 10+10+1 10+10+2 10+10+3
若是有第三次:10*3+0 10*3+1 10*3+2 10*3+3
。。。。。。