函数与生成器

一、函数属性

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

>>> 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 >>>

 

posted @ 2016-04-05 22:26 疯狂的杰瑞 阅读(...) 评论(...) 编辑 收藏