函数与生成器
一、函数属性
函数可以在内部创建默认的属性,还可以在外部通过句点属性标识符来动态创建该函数的属性。
>>> 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 >>>
软件即未来。