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)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值