知行编程网知行编程网  2022-11-09 04:30 知行编程网 隐藏边栏  3 
文章评分 0 次,平均分 0.0
导语: 本文主要介绍了关于python yield有什么用的相关知识,包括python中的yield用法,以及python中yield的作用这些编程知识,希望对大家有参考作用。

python产量有什么用

yield 是python函数定义中常用的关键字。它的作用是返回一个可用于迭代的生成器(for循环)。它的应用场景通常是一个需要返回一系列值并包含循环的函数。 .

要想完全理解yield关键字的用法,首先要理解以下几个词的含义:迭代、迭代、迭代器、生成器。接下来,我将一一介绍这些词的含义,以及对应的用法。


迭代(iteration)和可迭代(iterable)

迭代是一种操作。很多数据本身就是一种容器(container),它们包含了其他各种类型的数据,比如列表(list)、字典(dict)、元组(tuple)等等。我们在实践中使用这些容器时,往往需要从它们中一一获取数据。比如我们经常使用 for...in... 来打印列表中的数据,这个一个一个获取数据的过程就叫做迭代。

# iteration
a_list = [1, 2, 3]
for i in a_list:
    print(i)

可迭代是对象的一个​​特征,比如列表(list)是可迭代的,元组(tuple)是可迭代的,字典(dict)是可迭代的,字符串(string)是可迭代的,文件对象也是可迭代的。因为我们都可以从这些数据类型中一一获取数据。


迭代器(iterator)

迭代器是一次只能检索一个数据元素的对象。如果在迭代器上不断调用next()方法(将迭代变量作为参数放入next()中),可以依次获取下一个元素;当迭代器中没有元素时,调用next()方法会抛出StopIteration(停止迭代)异常。迭代器的 __iter__() 方法返回迭代器本身;因此迭代器也是可迭代的。

def liebiao():
for x in range(10):
yield x
 
g = liebiao()
 
#0
print(next(g))
 
#1
print(next(g))
 
#2
print(next(g))
 
#3
print(next(g))
 
#4
print(next(g))
 
#<generator object liebiao at 0x02C70E70>
g.__iter__()


生成器函数(generation function) 和 生成器(generation)

生成器函数是一种特殊的函数,它的函数包含一个yield表达式,调用它会返回一个特殊的迭代器,称为生成器。

def func():
    return 1
 
def gen():
    yield 1
 
print(type(func))   # <class 'function'>
print(type(gen))    # <class 'function'>
 
print(type(func())) # <class 'int'>
print(type(gen()))  # <class 'generator'>


yield表达式

如前所述,如果函数定义包含yield表达式,则该函数是生成器函数(不是普通函数)。实际上,yield 只能用于定义生成器函数。

与普通函数不同的是,调用生成器函数后,函数体中的代码不会立即执行,而是返回一个生成器-迭代器。当返回的生成器调用成员方法时,相应的生成器函数中的代码就会执行。

def square():
    for x in range(4):
        yield x ** 2
square_gen = square()
for x in square_gen:
    print(x)

如前所述,for循环会调用iter()函数来获取生成器;然后调用 next() 函数将生成器中的下一个值赋给 x;然后执行循环体。因此,上面的for循环基本等价于:

genitor = square_gen.__iter__()
while True:
    x = geniter.next() # Python 3 是 __next__()
    print(x)

注意 square 是一个生成器函数;作为它的返回值,square_gen 已经是一个迭代器;迭代器的 __iter__() 返回自身。因此,geniter对应的生成函数是方的。

每次执行 x = gniter.next() 时,square函数都会从上次暂停的位置开始,一直执行到下一个yield表达式,将yield关键字后面的表达式列表返回给调用者,然后再次暂停。请注意,生成器函数的内部变量、指令指针、内部评估堆栈等的内容与每次从暂停恢复时暂停时的内容完全相同。


换个说法

如果你不理解生成器函数,也就是带有yield关键字的函数,那么你可以这样理解:



·


在函数开始处,加入 result = list();



·


将每个 yield 表达式 yield expr 替换为 result.append(expr);



·


在函数末尾处,加入 return result。

也就是说,yield 的本质功能是返回一个可迭代的列表。


yield的好处

介绍了这么多定义和用法,为什么还要使用yield呢?它有什么好处?

很多情况下,我们需要一个一个地获取容器中的一些数据,而这种情况下,只是获取了一些元素,并不需要将容器中的所有元素都取出来。比如一个容器有10000个元素,但我们只需要前5个元素,那么解决方法通常如下:



·


获取容器内的所有元素,然后取出前 5 个;



·


从头开始,逐个迭代容器内的元素,迭代 5 个元素之后停止。

显然,如果容器中的元素数量非常多(比如 10 ** 8),或者容器中的元素体积非常大,那么后一种方案可以节省巨大的时间和空间开销。

现在假设我们有一个函数,其输出(返回值)是一个列表。而如果我们知道,函数调用者的返回值只能被一一迭代。那么,如果函数生成列表中的每个元素需要很长时间,或者生成所有元素需要很长时间,那么使用yield将函数变成一次只生成一个元素的生成器函数,并且可以节省大量开销。

python学习网,免费的在线学习
,欢迎关注!

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

知行编程网
知行编程网 关注:1    粉丝:1
这个人很懒,什么都没写
扫一扫二维码分享