Python初学者第二十四天 函数进阶(3)生成器
24day
1、列表生成式:
循环模式:[变量(加工后的变量) for 变量 in iterable]
print([i for i in range(0,101,2)]) [1,4,9,16,25,36,49] print([i*i for i in range(1,8)]) #['python1期', 'python2期', .....'python20期'] print(['python%s期'%i for i in range(1,21)])
筛选模式:[变量(加工后的变量) for 变量 in iterable if 条件]
[变量(加工后的变量) for 变量 in iterable if 条件] print([i for i in range(1,31) if i % 3 == 0]) print([i for i in range(1,31) if i % 3 == 0]) 30以内能被2整除的数的平方 print([ i*i for i in range(1,31) if i % 2 == 0]) [1,2,3,4,6,7,8] print([i for i in range(1,9)if i != 5]) l1 = ['wusir','ba', 'aa' ,'alex'] 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母 print([i.upper() for i in l1 if len(i) > 3]) ['WUSIR','ALEX'] names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] 将列表中的至少含有两个'e'的人名留下来。 l1 = [] for l in names: #正常情况 for name in l: if name.count('e') >= 2: l1.append(name) print(l1)
print([j for i in names for j in i if j.count('e')==2]) #列表生成式
1 >>> a = [i+1 for i in range(10)] 2 >>> a 3 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 4 >>> a = [i+1 for i in range(10)] 5 >>> a 6 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 7 >>> a = [i+1 for i in a] 8 >>> a 9 [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 10 >>> a = [i+1 for i in a] 11 >>> a 12 [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
通过列表生成式,我们可以直接创建一个列表
2、生成器:generator
生成器特性:
- 不占内存
- 只能向前,不能返回
- 当生成器达到要求会报错
创建generator,方法一:一个列表生成式的[]
改成()
,就创建了一个generator
>>> a3 = (i for i in range(5)) >>> a3 <generator object <genexpr> at 0x0000000001DF5BA0> >>> next(a3) 0 >>> next(a3) 1 >>> next(a3) 2 >>> next(a3) 3 >>> next(a3) 4 >>> next(a3) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
通过for循环来调用生成器
>>> a3 = (i for i in range(5)) >>> for i in a3: ... print(i) ... 0 1 2 3 4
通过while循环来调生成器(跳出循环会报错)
>>> a3 = (i for i in range(5)) >>> while True: ... next(a3) ... 0 1 2 3 4 Traceback (most recent call last): File "<stdin>", line 2, in <module> StopIteration
方法二:使用yield创建生成器(一个函数中包含yield关键字,那么这个函数就不在是一个普通的函数,而是一个generator)
generator和函数不一样。函数是按顺序执行,遇到return语句或最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时会从上一次返回的yield语句处继续执行。
return VS yield
return :返回并中止function
yield :返回数据,并冰冻当前的执行过程。next唤醒冻结的函数执行过程,直到遇到下一个yield
1 def fib(max): 2 n,a,b = 0,0,1 3 while n < max: 4 yield b #把函数的执行过程冻结在这一步,并且把b的值,返回给外面的next 5 print(b) 6 a,b = b,a+b 7 n += 1 8 return 'done' 9 10 f = fib(10) 11 next(f) 12 next(f) 13 next(f)
当函数里面存在同时存在yield和return时,return值无法返回
1 def range2(n): 2 count = 0 3 while count < n: 4 print('count',count) 5 count += 1 6 yield count 7 return 33333 8 9 new_range = range2(3) 10 n1 = next(new_range) 11 n2 = next(new_range) 12 n3 = next(new_range) 13 n4 = next(new_range)
#执行结果如下
Traceback (most recent call last):
count 0
count 1
count 2
File "D:/编辑的文本/生成器.py", line 27, in <module>
n4 = next(new_range)
StopIteration: 33333
3、生成器send
1 def range2(n): 2 count = 0 3 while count < n: 4 print('count',count) 5 count += 1 6 sign = yield count 7 print('sign',sign) 8 return 33333 9 10 new_range = range2(3) 11 n1 = next(new_range) 12 new_range.send('stop')
#执行结果:
count 0
sign stop
count 1
send------>>>>a、唤醒并继续执行;b、发送一个信息到生成器内部;
总结:
列表推导式 与生成器表达式区别;
1,列表推导式 一行搞定,构建简单。
2, 不能用debug排错,比较复杂的列表列表推导式不能推导出来。
生成器表达式:
1,循环模式。 (变量(加工后的变量) for 变量 in iterable)
(变量(加工后的变量) for 变量 in iterable if 条件)
1,一行搞定。
2,节省内存。