zoukankan      html  css  js  c++  java
  • python中的yield关键字

    yield关键字一直困扰了我很久,一直也没有弄明白,现在将暂时理解的yield记录如下,供参考:

    关键词:可迭代对象,生成器,迭代器

    一、可迭代对象:

    可迭代对象:可迭代对象是一个泛称,只要可以用for...in...处理的对象都可以称为可迭代对象。包括:列表(list)、元组(tuple)、字典(dict)、字符串(str)、文件(file)及迭代器和生成器。

    二、迭代器:

    迭代器:迭代器是一个对象,实现__iter__方法和__next__方法(只实现了__iter__方法的对象是可迭代的,并实现了__next__方法的对象是迭代器),迭代器通过调用__next__()方法获取下一个值;

    自定义迭代器(实现__iter__()方法和__next__()方法)

     class M(object):
        def __init__(self,max):
            self.max=max
            self.n=0
        def __iter__(self):
            return self
        def __next__(self):
            if self.n<self.max:
                self.n=self.n+1
                return self.n
            else:
                raise StopIteration  #一定要加上这一句,否则是无限循环了

    m=M(5)
    for i in m:
    print(i)
    输出结果:
    1
    2
    3
    4
    5

    三、生成器:

    生成器:生成器是一个函数,内部实现了yield关键字的函数都可称为生成器。

    生成器是特殊的迭代器。它不像list那样,将所有的数据都存储在内存中,那样占用极大的内存空间,而生成器每一次调用只返回一个数值,因此效率更高。

    生成器的优点:效率高,速度快,不占内存,优选使用生成器而不是list之类的可迭代对象

    生成器生成有两种个方式:

    1.(x*2 for x in range(5))即可返回一个生成器

    2.实现了yield关键字的函数。带有yield的函数就不再是一个普通的函数,而变成了一个生成器可以迭代了。

    yield理解:

    1.yield相当于普通函数中的return语句,yield语句右边即是其包含函数(生成器)要返回的值。

    2.每次迭代,运行完yield语句后暂停(即将yield右侧值返回),yield下一行语句等到下一次迭代再运行。

    3.生成器可以迭代的原因是内部实现了一个__next()__方法,每次迭代,运行一次__next__()方法,直到捕获到异常为止。

    4.迭代三种方式:for..in..循环;调用__next__()方法;调用send(msg)方法

    代码示例(来源于网络,https://www.jianshu.com/p/d09778f4e055):

    # encoding:UTF-8  
    def yield_test(n):
    for i in range(n):
    yield call(i)
    print("i=", i)
    # 做一些其它的事情
    print("do something.")
    print("end.")
    def call(i):
    return i * 2

    # 使用for循环
    for i in yield_test(5):
    print(i, ",")
    #或者使用__next__()方法
    for i in range(5):
    yield_test(5).__next__()

    输出结果:
    >>>   
    0 ,
    i= 0
    2 ,
    i= 1
    4 ,
    i= 2
    6 ,
    i= 3
    8 ,
    i= 4
    do something.
    end.
    >>>
    执行过程原理:
    生成器对象每次迭代,只返回一个数据(由yield返回),而这每次迭代就发生在for i in yield_test(5):的时候,这条语句的内部是调用了next(yield_test)函数。由于每次迭代只返回一个值,生成器内部只执行一次,因此对于生成器内的五次for循环,需要五次迭代才能完成。
    我们在分析运行过程时,要将迭代器看成一个蹦出值的机器,只有在通电(迭代)的时候机器才会运转一次,返回一个值,不要将生成器想的太复杂了。既然叫它生成器,它肯定是能够生产东西的机器,这个东西就是yield返回的那个数据。

    yield生成器的__next__()方法与send(msg)方法

    参考文章:

    1.为什么yield生成器第一次不能用send发送数据

    2.python的迭代器为什么一定要实现__iter__方法?

    由于生成器是惰性运行,即每次迭代只运行一次。我们定义一个迭代器:

    def h():
    print('wen chuan')
    m=yield 5#将yield 5当作一个整体,赋值给m
    print(m)
    n=yield 12
    print('together')

    if __name__=='__main__':
    g=h()#生成一个生成器
    print(type(g))#验证g的类型,打印值为<class 'generator'>
    g.__next__()#迭代一次
    print(g.send('haha'))
    打印结果:
    <class 'generator'>
    wen chuan
    haha
    12
    执行过程: 执行g.__next__(),程序运行到yield 5,将5返回,然后暂停。执行g.send('haha'),将yield 5当作整体,将‘haha'赋值给这个整体,并赋值给m,打印m值,再次运行到yield 12,将12返回。
    因此,send()函数除了具有__next__()一模一样的迭代作用外,还能够给jield x整体赋值。




  • 相关阅读:
    Zero Downtime Upgrade of Oracle 10g to Oracle 11g Using GoldenGate — 1
    架构-MVVM:MVVM核心概念
    架构-MVVC:百科
    架构:目录
    架构:template
    JavaScript-Tool:Ext JS
    JavaScript-Tool:jquery.tree.js-un
    JavaScript-Tool:wdtree
    C#:C# 运算符
    C#:目录
  • 原文地址:https://www.cnblogs.com/zhuluqing/p/8391760.html
Copyright © 2011-2022 走看看