python----生成式与生成器
#########列表生成式#########
#一般式:
[ experssion(或者函数) for item1 in 序列 if 判断语句
for item2 in 序列 if 判断语句
for item3 in 序列 if 判断语 ]
eg:接受变量k,a,b
s='51 5000 10000' k,a,b = [int(item) for item in s.split()] print(k,a,b)
#列表生存式for循环嵌套
li = [ [1,2,3], [4,5,6], [7,8,9] ] print([item2 for item1 in li for item2 in item1])
# 列表生成式使用变形:
1). [i**2 for i in range(2,10,2) ]
2). [fun(i) for i in range(2,10,2)]
3). [i**2 for i in range(2,10,2) if i%3==0]
4). [fun(i) for i in range(2,10,2) if i%3==0]
5). [fun(i) for i in range(2,10,2) if isFun(i)]
6). [fun1(i) if isFun(i) else fun2(i) for i in range(2,10,2)]
# 实现矩阵转置的两种方式
1). 列表生成式
2). 内置函数zip
li = [
[1,2,3,3,4],
[4,5,6,2,1],
[7,8,9,1,2]
]
# 方法1:
print([[ row[columnIndex] for row in li] for columnIndex in range(5)])
# columnIndex=0=====> 返回的是每一行的第0个索引值; [1,4,7]
# columnIndex=1=====> 返回的是每一行的第0个索引值; [2,5,8]
# 方法2:
# *li: 解包
# zip:
# 1).打包函数, 用于将可迭代的对象作为参数,
# 将对象中对应的元素打包成一个个元组,
# 然后返回由这些元组组成的列表。
# 2).如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,
# 利用 * 号操作符,可以将元组解压为列表
# 3). zip 方法在 Python 2 和 Python 3 中的不同:
# 在 Python 3.x 中为了减少内存,zip() 返回的是一个对象。
# 如需展示列表,需手动 list() 转换。
print(list(zip(*li)))
############字典生成式与集合生成式#############
#字典一般式:
{ key:value for item1 in 序列 if 判断语句
for item2 in 序列 if 判断语句
for item3 in 序列 if 判断语 }
eg:
import random stuInfo = {"westos" + str(i): random.randint(60, 100) for i in range(20)} print(stuInfo)
# 将字典的key值和value值调换;
d = {'a': 'apple', 'b': 'bob', 'c': 'come'} print({v: k for k, v in d.items()})
# 大小写计数合并 : key值最终全部为小写.
d1 = {'A': 10, 'b': 3, 'a': 5, 'B': 8, 'd': 1} print({k.lower(): d1.get(k.upper(), 0) + d1.get(k.lower(), 0) for k, v in d1.items()})
#字典生成式的嵌套集合生成式
import pprint import random pprint.pprint({ "user" + str(userItem): {"film" + str(fileItem) for fileItem in range(random.randint(4, 7))} for userItem in range(5)})
#集合生成式的一般式
{ experssion(或者函数) for item1 in 序列 if 判断语句
for item2 in 序列 if 判断语句
for item3 in 序列 if 判断语 }
s = {1, 2, 3, 4, 5, 6, 7} # 集合生成式 print({i ** 2 for i in s}) # 字典生成式 print({i: i ** 2 for i in s})
#############生成器################
#什么是生成器
在循环的过程中不断推算出后续的元素呢?这样就不必创
建完整的 list,从而节省大量的空间。在 Python 中,这种一
边循环一边计算的机制,称为生成器(Generator)
#实现生成器的方式
1.把一个列表生成式的 [] 改成 ()
2.使用yield实现
def isPrime(num): for i in range(2, num): if num % i == 0: return False else: return True #primeLi = [i for i in range(1,1000) if isPrime(i)] #把一个列表生成式的 [] 改成 () primeLi = (i for i in range(2,1000) if isPrime(i)) print(next(primeLi))
#怎么列出生成器里边的所有元素
1.把生成器对象转换为列表
2.用for循环遍历
from collections import Iterable
def isPrime(num):
for i in range(2, num):
if num % i == 0:
return False
else:
return True
#primeLi = [i for i in range(1,1000) if isPrime(i)]
primeLi = (i for i in range(2,100) if isPrime(i))
print(primeLi)
print(list(primeLi)) #把生成器对象转换为列表
print(isinstance(primeLi,Iterable)) #判断是否可以for循环
for i in primeLi: #.用for循环遍历
print(i)
#yield的使用
1. yield: 当函数中包含yield关键字, 返回值是一个生成器, 如果要执行函数内容.需要调用next方法, 或者for循环.
运行过程: 当执行next方法时, 遇到yield程序停止, 直到执行下一次next方法时,
从上一次停止的yield处继续执行,遇到yield停止运行.
eg:实现斐波那契数列(Fibonacci sequence)
def fib(num): """将来显示几个fib数列""" # count代表显示的已经 # a代表第一个数, b代表第二个数, count代表已经显示的fib个数,当前为0. a,b,count = 0,1,0 # 如果当前显示的个数小于需要显示的格式, 则显示b, 并且计算出下一个要显示的数。 while count < num: yield b a, b = b, a+b # 已经显示的次数加1; count += 1 # 生成器: 如果函数中有yield, 那么这个函数的返回值就是一个生成器; res=fib(100) print(next(res)) #print(next(res))会把yield之后的数b返回出来并且要运行到下一个yield print(next(res)) print(next(res)) print(next(res))#由此可以看出,生成器通过关键字 yield 不断的将迭代器返回到内存进行处理,而不会一次性的将对象全部放入内存,
# 从而节省内存空间。
2.生成器可以使用的方法:(next和send)
# 1. 函数中有yield, 返回值是一个生成器.
g = fun()
print(g)
# 2. 生成器函数默认不执行函数内容, 当next(g)时, 才执行函数内容.
# 3. 执行函数时, 一直执行, 遇到yield停止。 默认情况不会显示yield后面的内容,
# 如果要显示print(next(g))
next(g)
print(next(g))
print(next(g))
# 4. 如果需要给生成器函数传值
# 1). 必须有变量接收传递的值: res = yield 'yield3'
# 2). 通过g.send("hello")
# 3). send方法, 给yield所在位置传值, 接收值之后, 直到遇到yield停止.
g.send("hello")
def fun(): i=0 while i<100: i+=1 print(i) res= yield 'yield'+str(i) print(res) g=fun() print(g) next(g) #让函数运行,没有打印'yield'+str(i),到yield停止 g.send('hello') #给给函数发送'hello',函数用res接收,并运行到下一个yield print(next(g)) #运行到下一个yield并打印'yield'+str(i),但途中有个print(res)因为这一步没有send所以res=None
案例:生产者与消费者模型
import random import time # 缓冲区列表, 存放生产的所有包子,工作方式是队列的工作方式(FIFO-first in firest out). cacheList = [] # 如果缓冲区列表的长度为5, 缓冲区就满了, 生产者不能再生产了. cacheListLen = 5 def isfull(): # 缓冲区满了 return len(cacheList) == 5 def consumer(name): """消费者""" print("%s准备买包子......." % (name)) while True: kind = yield print("%s购买%s包子成功..." % (name, kind)) def producer(name): print("%s厨师正在生产包子......." % (name)) kinds = ['A', 'B', 'C', 'D'] while True: if not isfull(): # 模拟生产数据耗费的时间 time.sleep(random.random()) kind = random.choice(kinds) print("%s已经生产好%s包子了..." % (name, kind)) cacheList.append(kind) else: print("已经有足够的包子") yield p = producer("hello") next(p) consumers = [consumer('user' + str(i)) for i in range(4)] for i in consumers: if not cacheList: print("目前没有包子") else: # 如果缓冲区没有满, 就让生产者继续生产包子, 丛上次停止的地方继续执行. if not isfull(): next(p) # 从缓冲区拿出包子给消费者. kind = cacheList.pop() next(i) i.send(kind)