生成器和yield

作者: 东方胖 | 来源:发表于2018-09-10 11:39 被阅读149次

任何函数带 yield都会自动转换成生成器

例子:

def foo_func():
    print "> May not be printed this line"  (1)
    exit()
    yield "> This is generator"
    
foo_func()

调用 foo_func() 会发现 第(1)行不会打印

这是因为

关键字 yield 一旦出现在函数内部 函数就会自动转为一个生成器,生成器只有使用next方法才会被调用

如上

x = foo_func()
print(next(x))

生成器内置迭代器,请看:

dir(x) #x是一个生成器

[
'__class__', '__del__', '__delattr__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', 
'__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__',
'__le__', '__lt__', '__name__', '__ne__', '__new__',
'__next__', '__qualname__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__',
'close', 'gi_code', 'gi_frame', 'gi_running',
'gi_yieldfrom', 'send', 'throw'
]

生成器对象实现了 iter 协议,因此它是可迭代对象,可以使用for Loop迭代

例子:

def one_to_ten():
    val = 1
    while val <= 10:
        #print val
        yield val
        val += 1

for ele in one_to_ten():
    print ele
  • 生成器 是一种特殊的迭代器

  • 一旦一个函数中包含了关键字 yield 那么它就会自动转化为一个生成器

  • 生成器有异于一般函数的使用方式

神奇的yield

当一个生成器函数的 yield 被调用的时候,函数的内部状态就被“冻结”起来,函数内部的变量和值被保存起来。
下一行的代码直到next()方法调用才会再次被执行

next执行的时候,生成器在它上次被中断的地方恢复所有状态,并继续执行,直到下一个yield出现


def is_prime(number):
    if number == 2:
        return True

    i = 2
    while i * i <= number:
        if number % i == 0:
            return False
        i += 1
    else:
        return True


def get_prime(number):
    while True:
        if is_prime(number):
            yield number
        number += 1

for element in get_prime(2):
    print(element)

记住这些:

  • generators 用来生成一系列的值
  • yield 在生成器中的作用类似于 return;区别在于,yield保存了函数的局部状态,但return在函数中,会转移控制权,导致整个函数内部丢失所有状态
  • 生成器是一种特殊的迭代器(即它实现了内部协议 iter)因此像迭代器一样,生成器可以用next()得到下一个值

相关文章

网友评论

    本文标题:生成器和yield

    本文链接:https://www.haomeiwen.com/subject/eyfsgftx.html