Python基础 - 06推导式及生成器
一、列表推导式
格式: [表达式 for 变量 in 旧列表] [表达式 for 变量 in 旧列表 if 条件]
names = ['tom', 'lily', 'abc', 'Hello', 'Jack', 'lucy'] result1 = [name for name in names if len(name) > 3] print(result1) # ['lily', 'Hello', 'Jack', 'lucy'] result2 = [name.capitalize() for name in names if len(name) <= 3] print(result2) # ['Tom', 'Abc'] # 将1-100之间被3整除的数字组成一个列表 result3 = [num for num in range(1, 101) if num % 3 == 0] print(result3) result4 = [num for num in range(1, 101) if num % 3 == 0 and num % 5 == 0] print(result4)
# 0-5 偶数 0-10 奇数 (0,1) (0,3) ... (0,9) (2,1) (2,3) ... result5 = [(x, y) for x in range(5) if x % 2 == 0 for y in range(10) if y % 2 != 0] print(result5)
employee1 = {'name': 'zhangsan', 'salary': 4300} employee2 = {'name': 'lisi', 'salary': 5500} emp = [employee1, employee2] n = [employee['salary'] + 200 if employee['salary'] > 4500 else employee['salary'] + 500 for employee in emp] print(n) # [4800, 5700]
二、字典推导式、集合推导式
list1 = [1, 2, 3, 1, 5, 3, 2, 6, 8, 9, 8, 8, 9]
set1 = {x - 1 for x in list1 if x > 5} # 类似列表推导式,没有重复元素
print(set1) # {8, 5, 7}
dict1 = {'k1': 'v1', 'k2': 'v2'}
newdict = {value: key for key, value in dict1.items()}
print(newdict) # {'v1': 'k1', 'v2': 'k2'}
三、生成器
使用列表推导式生成列表,但受到内存限制,容量有限。 创建一个100万元素的列表,仅仅需要访问前面几个元素,造成空间浪费。
边循环边计算的机制,称为生成器, generator
next(generator): 每次调用都会产生一个新的元素,如果元素都产生完毕,再次调用会产生异常。
生成器方法: g.__next__() g.send(value)
3.1 定义生成器
list2 = [x * 3 for x in range(10)]
print(type(list2)) # <class 'list'>
g = (x * 3 for x in range(5))
print(type(g)) # <class 'generator'>
print(g) # <generator object <genexpr> at 0x000000DC2790DF90>
print(g.__next__()) # 0
print(g.__next__()) # 3
print(g.__next__()) # 6
print(next(g)) # 9
print(next(g)) # 12
#print(next(g)) # StopIteration
3.2 使用try...except 结构读取生成器元素; 读取读取的方式 next(g) 或 g.__next__()
while True:
try:
e = next(g)
print(e)
except:
print('没有元素啦')
break
print('测试结束')
'''
0
3
6
9
12
没有元素啦
测试结束
'''
3.3 定义生成器方式: 函数
# 定义生成器方式二: 函数
# 只要函数中出现yield关键字,则函数不再是函数,变成生成器了。
def func6():
n = 0
while True:
n += 1
# print(n)
yield n # 效果等同于 return n + 暂停
g = func6()
print(g) # <generator object func6 at 0x0000008356E8DF20>
print(next(g)) # 1
print(next(g)) # 2
使用生成器实现斐波那契数列:
def fib(length): a, b = 0, 1 n = 0 while n < length: yield b a, b = b, a + b n += 1 g = fib(8) print(next(g)) # 1 print(next(g)) # 1 print(next(g)) # 2 print(next(g)) # 3 print(next(g)) # 5 print(next(g)) # 8 print(next(g)) # 13 print(next(g)) # 21
def fib(length): a, b = 0, 1 n = 0 while n < length: print(b) a, b = b, a + b n += 1 fib(8) # 也能实现输出 1 1 2 3 5 8 13 21
3.4 生成器带return语句
def fib(length): a, b = 0, 1 n = 0 while n < length: yield b a, b = b, a + b n += 1 return 'abc' g = fib(8) print(next(g)) # 1 print(next(g)) # 1 print(next(g)) # 2 print(next(g)) # 3 print(next(g)) # 5 print(next(g)) # 8 print(next(g)) # 13 print(next(g)) # 21 print(next(g)) # StopIteration: abc ;没有 return时,报错StopIteration
3.5 send方法: 向生成器中传值
def gen():
i = 0
while i < 5:
temp = yield i
print('temp: ', temp)
i += 1
return '没有数据了'
g = gen()
print(g.__next__()) # 0
print(g.__next__()) # temp: None \n 1
print(g.__next__()) # temp: None \n 2
n1 = g.send('呵呵')
print('n1: ', n1) # temp: 呵呵 \n n1: 3
n2 = g.send('哈哈')
print('n2: ', n2) # temp: 哈哈 \n n2: 4
n3 = g.send(None) # temp: None \n StopIteration: 没有数据了, 取值时没有了报错,赋值成功
print('n3: ', n3) # 这个没有执行
直接往生成器非None传值报错
g = gen() # print(g.__next__()) # print(g.__next__()) # print(g.__next__()) n1 = g.send('呵呵') # 报错: # TypeError: can't send non-None value to a just-started generator
g = gen() print(g.send(None)) # 改成 n = g.send(None) 也可以 n1 = g.send('呵呵') print('n1: ', n1) ''' 0 temp: 呵呵 n1: 1 '''
def gen1():
i = 0
while i < 5:
temp = yield i
print('temp: ', temp)
for i in range(temp):
print('------->', i)
print('**************')
i += 1
return '没有数据了'
g1 = gen1()
print(g1.send(None))
n1 = g1.send(3)
print('n1:',n1)
'''
0
temp: 3
-------> 0
-------> 1
-------> 2
**************
n1: 3
'''
n2 = g1.send(4)
print('n2:', n2)
'''
temp: 4
-------> 0
-------> 1
-------> 2
-------> 3
**************
n2: 4
'''
def task1(n):
for i in range(n):
print('正在搬第{}块砖'.format(i+1))
yield None
def task2(n):
for i in range(n):
print('正在听第{}首歌'.format(i+1))
yield None
g1 = task1(3)
g2 = task2(2)
while True:
g1.__next__()
g2.__next__()
'''
正在搬第1块砖
正在听第1首歌
正在搬第2块砖
正在听第2首歌
正在搬第3块砖
Traceback (most recent call last):
File "E:\PythonLearn\pythonBase\02door2\08-generator-03.py", line 23, in <module>
g2.__next__()
StopIteration
'''
处理异常:
while True: try: g1.__next__() g2.__next__() except: pass
3.6 可迭代与迭代器
# 可迭代的对象 1. 生成器 2. 元祖 列表 集合 字典 字符串
# 如何判断一个对象是否可迭代
from collections import Iterable
list1 = [1,2,46,5,3]
result = isinstance(list1, Iterable)
print(result) # True
result = isinstance('abc', Iterable)
print(result) # True
result = isinstance(100, Iterable)
print(result) # False
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有元素都被访问完结束。迭代器只能往前不会后退。
# 可以被next()函数调用并返回下一个值的对象称为迭代器:Iterable。
# 可迭代的 不一定就是迭代器。
# 生成器是可迭代的,是迭代器。 list是可迭代的,但不是迭代器。
list1 = iter(list1)
print(next(list1)) # 1
print(next(list1)) # 2