• 函数与生成器


    一、函数属性

    函数可以在内部创建默认的属性,还可以在外部通过句点属性标识符来动态创建该函数的属性。

    >>> def foo():
        'foo() -- properly created doc string!'
    >>> def bar():
        pass
    
    >>> foo.__doc__
    'foo() -- properly created doc string!'
    >>> bar.__doc__
    >>> bar.version = 0.1
    >>> bar.version
    0.1
    >>> bar.hehe = 1
    >>> bar.hehe
    1

     二、生成器:generator

    一边循环,一边计算的机制,称为生成器,每次循环只会取出一个元素,可以节省大量内存空间。

    1、通过小括号的方式创建生成器:(),并用next()函数输出每一个元素

    # 使用中括号时是列表推导式:
    >>> L = [x * x for x in range(10)]
    >>> L
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    # 使用小括号时是生成器:
    >>> g = (x * x for x in range(10))
    >>> g
    <generator object <genexpr> at 0x000002299458AF68>
    
    >>> # 生成器取出元素可以使用next()函数,一次取出一个元素:
    >>> next(g)
    0
    >>> next(g)
    1
    >>> next(g)
    4
    >>> next(g)
    9
    >>> next(g)
    16
    >>> next(g)
    25
    >>> next(g)
    36
    >>> next(g)
    49
    >>> next(g)
    64
    >>> next(g)
    81
    # 取到最后时会抛出StopIteration异常,不能再取出元素:
    >>> next(g)
    Traceback (most recent call last):
      File "<pyshell#15>", line 1, in <module>
        next(g)
    StopIteration
    >>> 

    2、使用for循环取出生成器中的元素:

    >>> g = (x * x for x in range(10))
    >>> for i in g:
        print(i)    
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81

    3、在函数中使用yield语法构造生成器:

    1)使用函数打印斐波那契数列:

    >>> def fib(max):
        n,a,b = 0,0,1
        while n < max:
            print(b)
            a,b = b,a+b
            n += 1
        return 'done'
    
    >>> fib(6)
    1
    1
    2
    3
    5
    8
    'done'

    2、修改函数使它成为一个生成器而不再是函数:

    >>> def fib(max):
        n,a,b = 0,0,1
        while n < max:
            yield b
            a,b = b,a+b
            n += 1
        return 'done'
    
    >>> fib
    <function fib at 0x00000229945A0378>

    ** 函数和生成器的区别在于,生成器有yield,而yield的机制是遇到此语句后即返回,然后继续执行函数内后面的语句,而函数中的return语句是直接从函数返回,不会再执行后面的语句。

    可以通过for迭代语句取出每次返回的yield值:

    >>> for n in fib(6):
        print(n)
    
        
    1
    1
    2
    3
    5
    8

    同样也可以使用next()函数迭代生成器:

    # 注意这里的f = fib(6)是必须有的,这个表示可迭代对象,且只运行一次生成器,如果使用next(fib(6)),那么每次next都会执行一次生成器,也就只会执行到第一次yield。
    >>> f = fib(6)
    >>> next(f)
    1
    >>> next(f)
    1
    >>> next(f)
    2
    >>> next(f)
    3
    >>> next(f)
    5
    >>> next(f)
    8
    # 可以看到在没有yield语句后引发了异常,而异常的value值就是生成器 >>> next(f) Traceback (most recent call last): File "<pyshell#57>", line 1, in <module> next(f) StopIteration: done >>>
  • 相关阅读:
    利用Trace.WriteLine定位难以重现的问题
    技术经验分享
    辞职小记
    残阳如血--读《忆秦娥·娄山关》 有感
    一个简单多线程等待窗口
    [转]Control的Invoke和BeginInvoke
    elk 改为使用 ik 中文分词器
    在 jenkins 的 pipeline 中使用分支参数
    centos8 下删除网桥 docker0
    vscode 实现组件之间的跳转
  • 原文地址:https://www.cnblogs.com/OnOwnRoad/p/5357169.html
Copyright © 2020-2023  润新知