Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

python之路 - 函数与模块2

$
0
0

1.列表生成式

1 list1 = [x*2 for x in range(1,11)] View Code

可以用列表生成式快速生成一个列表,但是受到内存限制,列表的容量是有限的,一个列表中假如有100万个元素,我们只使用了其中的几个,不仅占用大量内存,绝大多数空间是被浪费掉了

如果列表中的元素可以按照某种算法推算出来,那我们可以在循环中不断推算出后面的结果,这样就不必创建列表和浪费大量内存空间了

2.生成器

python中一边循环一边计算的方式叫generator生成器

要创建一个generator,有很多种方法,第一种方法很简单,只要把一个列表生成式的 [] 改成 () ,就创建了一个generator 1 list1 = [x*2 for x in range(1,11)] 2 3 g = (x*2 for x in range(1,11)) View Code

g就是一个生成器

如何打印生成器的每个元素呢

1 g.__next__() 2 或者 3 next(g) View Code

generator保存的是算法,每次调用 next(g) ,就计算出 g 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出 StopIteration 的错误

当然,上面这种不断调用 next(g) 实在是太变态了,正确的方法是使用 for 循环,因为generator也是可迭代对象

1 for i in g: 2 print (i) View Code

所以,我们创建了一个generator后,基本上永远不会调用 next() ,而是通过 for 循环来迭代它,并且不需要关心 StopIteration 的错误

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的 for 循环无法实现的时候,还可以用函数来实现

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易

1 def fib(max): 2 n,a,b = 0,1,1 3 while n<max: 4 print (b) 5 a,b = b,a+b 6 n = n + 1 7 return "done" View Code

注意一点,里面的赋值

a,b = b,a+b

实际上是 t = (b,a+b)

a = 1

b = 2

t = (2,3)

a,b = (2,3)

仔细观察,可以看出, fib 函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把 fib 函数变成generator,只需要把 print(b) 改为 yield b 就可以了

1 def fib(max): 2 n,a,b = 0,1,1 3 while n<max: 4 yield b 5 a,b = b,a+b 6 n = n + 1 7 return "done" View Code

这就是定义generator的另一种方法。如果一个函数定义中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个generator

这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用 next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行

for 循环调用generator时,发现拿不到generator的 return 语句的返回值。如果想要拿到返回值,必须捕获 StopIteration 错误,返回值包含在 StopIteration 的 value 中

1 g = fib(6) 2 while True: 3 try: 4 x = next(g) 5 print('g:', x) 6 except StopIteration as e: 7 print('Generator return value:', e.value) 8 break View Code

还可通过yield实现在单线程的情况下实现并发运算的效果

1 #!/usr/bin/env python 2 #_*_ coding:utf-8 _*_ 3 # Author: jiachen 4 5 import time 6 7 def consumer(name): 8 print ("%s 准备吃包子啦!" % name) 9 while True: 10 baozi = yield 11 print ("包子[%s]来了,被[%s]吃了" % (baozi,name)) 12 13 def producer(): 14 c1 = consumer("Jack") 15 c2 = consumer("Tom") 16 c1.__next__() 17 c2.__next__() 18 for i in range(1,11): 19 time.sleep(1) 20 print ("做好1个包子,分成两份!") 21 c1.send(i) 22 c2.send(i) 23 producer() View Code

Viewing all articles
Browse latest Browse all 9596

Trending Articles