yield关键字

如果是第一次遇到这个关键字,可以直接使用下文中小标题为Next的代码设置断点看一下效果

  1. yield的函数是一个生成器,而不再是一般意义上的一个函数。yield在函数中的功能类似于return,不同的是yield每次返回结果之后函数并没有退出,而是 每次遇到yield关键字后返回相应结果,并保留函数当前的运行状态,等待下一次的调用。
  2. 包含yield的函数成为一个生成器(一开始不运行,而是得到一个对象),生成器同时也是一个迭代器,支持通过next方法获取下一个值。
  3. 使用yield的好处是通过使用生成器,避免占用内存,提高运行效率。

适用场景:一个函数需要多次循环执行一个动作,并且每次执行的结果都是需要的

示例

def foo():
    print("starting...")
    while True:
    result = yield 4
    print("result:", result)


test = foo()
print(next(test))
print("*"*20)
print(next(test))

输出

starting...
4
********************
result: None
4

代码分析:

(1) 针对test = foo(),由于函数foo中存在yield关键字,所以函数foo内的代码一开始并不执行,而是得到一个生成器test(相当于一个对象)。

(2) 针对print(next(test))。由于调用了next方法,foo函数开始执行。先输出starting...,然后进入while循环。在循环内,遇到yield关键字。这里可以把yield想象成return。因此,foo函数返回4,并通过print函数输出。注意:这里并没有执行result的赋值操作。

(3) 针对print("*"*20)。程序输出20个星号。

(4)针对print(next(test))。这句代码是接着步骤(2)结束的地方开始执行,执行的是result的赋值操作。注意:由于在步骤(2)的时候,4已经return出去,并没有完成赋值操作。因此,现在给result赋的值是None。所以输出的结果是result: None。程序接着在While内继续执行,又一次碰到yield关键字,同样返回4,并通过print函数输出。

总结一下,带yield的函数是一个生成器,而不再是一般意义上的一个函数了,这个生成器有一个方法就是next方法,next就相当于“下一步”生成哪个数,这一次的next开始的地方是接着上一次的next停止的地方执行的,所以第二次调用next的时候,生成器并不会从foo函数最开始的地方执行,而是接着上一步停止的地方开始,然后遇到yield后,return出要生成的数,此步就结束。

Next

def count_up_to(limit):
    count = 1
    while count <= limit:
        yield count
        count += 1

# 使用生成器函数
generator = count_up_to(5)

# 调用 next() 函数获取生成器的下一个值
print(next(generator))  # 输出 1
print(next(generator))  # 输出 2
print(next(generator))  # 输出 3
print(next(generator))  # 输出 4
print(next(generator))  # 输出 5
# 超过 limit,再次调用将抛出 StopIteration 异常
# 如果在循环中使用,可以通过捕获异常来结束循环
# 或者使用 for 循环,它会自动处理 StopIteration 异常

Send

除了next方法,yield得到的生成器还支持send方法。该方法可以向生成器传递参数。

python yield用法 (baidu.com)

避免占用内存

  1. 通常的for…in…循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件。它可以是mylist 
    = [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。 它的缺陷是所有数据都在内存中,如果有海量数据的话将会非常耗内存。
  2. 生成器是可以迭代的,但只可以读取它一次。因为用的时候才生成。比如 mygenerator = (x*x for x in range(3)),注意这里用到了(),它就不是数组,而上面的例子是[]。

你可能感兴趣的:(python,python,开发语言)