Python 教程中的 Yield:生成器和 Yield 与 Return 示例
Python yield 是什么?
Python 中的 yield 关键字的工作方式类似于 return,唯一的
区别在于,它不是返回一个值,而是将一个生成器对象返回给调用者。
当调用一个函数,并且执行流遇到函数中的 yield 关键字时,函数执行将在该行停止,并将生成器对象返回给调用者。
语法
yield expression
描述
Python yield 返回一个生成器对象。生成器是特殊的函数,必须迭代才能获得值。
yield 关键字将给定的表达式转换为生成器函数,该函数返回一个生成器对象。要获取对象的值,必须对其进行迭代才能读取给 yield 的值。
示例:Yield 方法
这是一个简单的 yield 示例。testyield() 函数包含一个 yield 关键字,值为“Welcome to Guru99 Python Tutorials”。当调用函数时,输出将被打印,并且它会返回一个生成器对象而不是实际值。
def testyield(): yield "Welcome to Guru99 Python Tutorials" output = testyield() print(output)
输出
<generator object testyield at 0x00000028265EB9A8>
输出的是一个生成器对象,其中包含我们赋给 yield 的值。
但是我们没有在输出中看到我们赋给 yield 的消息!
要打印赋给 yield 的消息,您需要迭代生成器对象,如下面的示例所示。
def testyield(): yield "Welcome to Guru99 Python Tutorials" output = testyield() for i in output: print(i)
输出
Welcome to Guru99 Python Tutorials
Python 中的生成器是什么?
生成器是返回可迭代生成器对象的函数。生成器对象中的值是一次获取一个,而不是一次性获取整个列表,因此要获取实际值,可以使用 for 循环,使用 next() 或 list() 方法。
使用生成器函数
您可以使用生成器函数和生成器表达式来创建生成器。
生成器函数就像一个普通函数,但它没有返回值,而是有一个 yield 关键字。
要创建生成器函数,您需要添加一个 yield 关键字。以下示例显示了如何创建生成器函数。
def generator(): yield "H" yield "E" yield "L" yield "L" yield "O" test = generator() for i in test: print(i)
输出
H E L L O
普通函数与生成器函数的区别。
让我们了解生成器函数与普通函数的区别。
有两个函数 normal_test() 和 generator_test()。
这两个函数都应该返回字符串“Hello World”。normal_test() 使用 return,而 generator_test() 使用 yield。
# Normal function def normal_test(): return "Hello World" #Generator function def generator_test(): yield "Hello World" print(normal_test()) #call to normal function print(generator_test()) # call to generator function
输出
Hello World <generator object generator_test at 0x00000012F2F5BA20>
输出显示,当您调用普通函数 normal_test() 时,它会返回 Hello World 字符串。对于带有 yield 关键字的生成器函数,它返回 <generator object generator_test at 0x00000012F2F5BA20> 而不是字符串。
这是生成器函数和普通函数之间的主要区别。现在,要从生成器对象中获取值,我们需要在 for 循环中使用该对象,或者使用 next() 方法,或者使用 list()。
print(next(generator_test())) # will output Hello World
普通函数与生成器函数还有另一个区别,即当您调用普通函数时,执行将开始,并在遇到 return 时停止,然后将该值返回给调用者。因此,当执行开始时,您无法在中间停止普通函数,它只会停止在遇到 return 关键字时。
但是对于生成器函数,一旦执行开始,当它遇到第一个 yield 时,它会停止执行,并将生成器对象返回给调用者。您可以使用生成器对象来获取值,还可以根据需要暂停和恢复执行。
如何从生成器读取值?
您可以使用 list()、for 循环和 next() 方法从生成器对象读取值。
使用: list()
列表是一个可迭代对象,其元素包含在括号内。对生成器对象使用 list() 将获得生成器拥有的所有值。
def even_numbers(n): for x in range(n): if (x%2==0): yield x num = even_numbers(10) print(list(num))
输出
[0, 2, 4, 6, 8]
使用: for-in
在示例中,有一个名为 even_numbers() 的函数,它将为您提供 n 定义的所有偶数。对 even_numbers() 函数的调用将返回一个生成器对象,该对象在 for 循环中使用。
示例
def even_numbers(n): for x in range(n): if (x%2==0): yield x num = even_numbers(10) for i in num: print(i)
输出
0 2 4 6 8
使用 next()
next() 方法将为您提供列表、数组或对象中的下一个项。一旦列表为空,如果调用 next(),它将返回一个错误,并带有 stopIteration 信号。此错误来自 next(),表示列表中没有更多项了。
def even_numbers(n): for x in range(n): if (x%2==0): yield x num = even_numbers(10) print(next(num)) print(next(num)) print(next(num)) print(next(num)) print(next(num)) print(next(num))
输出
0 2 4 6 8 Traceback (most recent call last): File "main.py", line 11, in <module> print(next(num)) StopIteration
生成器是一次性使用的
对于生成器,它们只能使用一次。如果您再次尝试使用它们,它们将是空的。
例如
def even_numbers(n): for x in range(n): if (x%2==0): yield x num = even_numbers(10) for i in num: print(i) print("\n") print("Calling the generator again: ", list(num))
输出
0 2 4 6 8 Calling the generator again: []
如果您希望再次使用输出,您将需要再次调用该函数。
示例:生成器和 yield 用于 Fibonacci 序列
以下示例展示了如何在 Python 中使用生成器和 yield。该示例将生成 Fibonacci 序列。
def getFibonnaciSeries(num): c1, c2 = 0, 1 count = 0 while count < num: yield c1 c3 = c1 + c2 c1 = c2 c2 = c3 count += 1 fin = getFibonnaciSeries(7) print(fin) for i in fin: print(i)
输出
<generator object getFibonnaciSeries at 0x0000007F39C8BA20> 0 1 1 2 3 5 8
示例:调用带 yield 的函数
在此示例中,我们将看到如何调用带 yield 的函数。
下面的示例有一个名为 test() 的函数,它返回给定数字的平方。还有一个名为 getSquare() 的函数,它使用带 yield 关键字的 test()。输出会给出给定数字范围的平方值。
def test(n): return n*n def getSquare(n): for i in range(n): yield test(i) sq = getSquare(10) for i in sq: print(i)
输出
0 1 4 9 16 25 36 49 64 81
何时在 Python 中使用 Yield 而不是 Return
Python3 Yield 关键字向调用者返回一个生成器,代码的执行仅在生成器被迭代时开始。
函数中的 return 是函数执行的结束,并向调用者返回单个值。
以下是您应该使用 Yield 而不是 Return 的情况
- 当数据量很大时,请使用 yield 而不是 return
- 当您希望在大型数据集上提高执行速度时,yield 是最佳选择。
- 当您想将大量值返回给调用函数时,请使用 yield。
- Yield 是一种高效的生成大数据或无限数据的方式。
Yield 与 Return
以下是 Yield 和 Return 之间的区别
Yield | 退货 |
---|---|
Yield 向调用者返回一个生成器对象,代码的执行仅在生成器被迭代时开始。 | 函数中的 return 是函数执行的结束,并向调用者返回单个值。 |
当调用函数并遇到 yield 关键字时,函数执行会停止。它将生成器对象返回给调用者。函数执行仅在生成器对象执行时才开始。 | 当调用函数时,执行开始,如果存在 return 关键字,则将值返回给调用者。函数中的 return 标记着函数执行的结束。 |
yield 表达式 | return 表达式 |
使用 yield 关键字时,不使用内存。 | 为返回的值分配内存。 |
如果您需要处理大量数据,这将非常有用,因为不使用内存。 | 对于非常小的数据集来说很方便。 |
如果使用 yield 关键字处理大数据,性能会更好。 | 如果数据量很大,会消耗大量内存,从而影响性能。 |
对于大数据,yield 的执行时间更快。 | 执行时间更长,因为对于大数据集会进行额外的处理,如果数据集很小,它会正常工作。 |
摘要
- Python 中的 yield 关键字的工作方式类似于 return,唯一的区别是它不返回一个值,而是将一个生成器函数返回给调用者。
- 生成器是一种特殊的迭代器,一旦使用,将不再可用。这些值不存储在内存中,只有在调用时才可用。
- 可以通过 for-in、list() 和 next() 方法从生成器读取值。
- yield 和 return 的主要区别在于,yield 向调用者返回一个生成器函数,而 return 向调用者返回一个单个值。
- Yield 不会在内存中存储任何值,其优点在于处理大数据集时非常有用,因为不会存储任何值。
- 与 return 相比,如果使用 yield 关键字处理大数据,性能会更好。