iOS开发人员如何学习Python编程13-函数4

这是我参与11月更文挑战的13天,活动详情查看:2021最后一次更文挑战

生成器(generator

列表所有数据都在内存中,如果有海量数据的话会非常消耗内存。

例如,我们仅仅需要访问前面几个元素,但后面绝大多元素占用的内存就会浪费了。
那么生成器就是在循环的过程中根据算法不断推算出后续的元素,这样就不用创建整个完整的列表,从而节省大量的空间。
总而言之,就是当我们想要使用庞大数据,又想让它占用的空间少,那就使用生成器。

如何创建生成器

生成器表达式

生成器表达式来源于迭代和列表解析的组合,生成器和列表解析类似,但是它使用()而不是[]

g = (x for x in range(5))
print(g)       # generator object
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# 超出报错
print(next(g))

for i in g:
    print(i)
复制代码

生成器

当一个函数中包含yield关键字,那么这个函数就不再是一个普通的函数,而是一个generator生成器表达式来源于迭代和列表解析的组合,生成器和列表解析类似,但是它使用()而不是[]。 调用函数就是创建了一个生成器对象。其工作原理就是通过重复调用next()或者__next__()方法,直到捕获一个异常:

def yieldtest(number):
    n = 0
    # li = []
    while n<number:
        # li.append(n)
        yield n
        n+=1

res = yieldtest(20)
print(res)       # generator object
print(next(res)) # 0
print(next(res)) # 1
print(next(res)) # 2
复制代码

⚠️注意:

  • yield返回一个值,并且记住这个返回值的位置,下次遇到next()调用时,代码从yield的下一条语句开始执行。与return的差别是,return也是返回一个值,但是直接结束函数。

例如,实现斐波那契数列。除第一个和第二个数外,任何一个数都可以由前两个相加得到:1,1,2,3,5,8,12,21,34.....

def createNums():
    print("-----func start-----")
    a,b = 0,1
    for i in range(5):
        # print(b)
        print("--1--")
        yield b
        print("--2--")
        a,b = b,a+b
        print("--3--")
    print("-----func end-----")
    
g = createNums()
print(next(g))  
print(next(g))  
print(next(g))
print(next(g))
print(next(g))
复制代码

send()

send() 和next()一样,都能让生成器继续往下走一步(遇到yield返回),但send()能传一个值,这个值作为yield表达式整体的结果:

def test():
    a1 = yield "hello"
    print("---1---")
    yield a1

res = test()
print(next(res))          # "hello"
print(res.send("world"))  # "world"
复制代码

也就是说,通过send方法可以强行修改上一个yield表达式值。

比如函数中有一个yield赋值:

a1 = yield "hello"
复制代码
  1. 第一次迭代到这里会返回"hello",但是a1还没进行赋值;
  2. 第二次迭代时,使用.send("world")
  3. 那么,就是相当于强行修改yield "hello"表达式的值为"world"
  4. 所以yield a1结果为"world"

猜你喜欢

转载自juejin.im/post/7031706332734586917