day 15 生成器面试题

Posted by tzwlwy's Blog on January 3, 2021

学习了生成器后自信满满,结果被上了一课,我们先来看题,第一题相对简单,但是也错了

def demo():
    for i in range(4):
        yield i

g=demo()
g1=(i for i in g)
g2=(i for i in g1)
print("g1结果如下:")
print(list(g1))
print("g2结果如下:")
print(list(g2))

答案: 
g1结果如下:
[0, 1, 2, 3, 4]
g2结果如下:
[]
跟我预想的不太一样,我预想是,g1=[] ,g2=[0, 1, 2, 3, 4],结果事实刚好相反
因为生成器没运行的时候值是不取出来的,所以g1=(i for i in g)时,可以理解为值仍然在g里,
运行g2=(i for i in g1) 时,可以理解为值仍然在g1里
当运行print(list(g1))时,一个个从g1里面取,g1 从g里面取,所以g1=[0, 1, 2, 3, 4]
在运行print(list(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("g结果如下:")
print(list(g))
print("g1结果如下:")
print(list(g1))
print("g2结果如下:")
print(list(g2))

# g结果如下:
# [0, 1, 2, 3]
# g1结果如下:
# []
# g2结果如下:
# []

然后是第二个面试题,输出结果是什么

 def add(a,b):
    return a+b

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))

看到这个膨胀的很,不就是生成器加推导式么,咦,应该会报错吧,g有4个数,n只有2个数,结果是我年轻了。。。
首先进行拆分
for n in [1,10]:
    g=(add(n,i) for i in g)
同等于
n=1
g=(add(n,i) for i in g)
n=10
g=(add(n,i) for i in g)
也就是同等于
g=(add(n,i) for i in (add(n,i) for i in g)) 
#注意这里n全都为10,因为是生成器,所以n=1时没执行,在执行print(list(g)) 时n=10 
g=(add(10,i) for i in (add(10,i) for i in test())) 

g=(add(10,i) for i in (10,11,12,13) 
g=(20,21,22,23)
print(list(g)) #[20, 21, 22, 23]

总结:


生成器是惰性的,所以要看执行时往上调,而不是想当然的理解拆分为
g=(add(10,i) for i in (add(1,i) for i in test()))