Python学习--Day 18

135.列表推导式

  • 列表推导式:将旧列表转换为符合需求的新列表,与此相类似的还有字典推导式、集合推导式、字典推导式。
  • 列表推导式的格式:[待执行的表达式 for 变量 in 旧列表] 或者[待执行的表达式 for 变量 in 旧列表 if 条件],就是简化了以前繁琐的代码。
    举个例子:
names = ['tom','lily','abc','jack','steven','bob','ha']
re = [name for name in names if len(name)>3] # 符合条件的就保留
print(re)
# 返回结果:
# ['lily', 'jack', 'steven']w
rew = [name.capitalize() for name in names] # 将列表的内容首字符大写
print(rew)
# 返回结果:
# ['Tom', 'Lily', 'Abc', 'Jack', 'Steven', 'Bob', 'Ha']

-实战:将1-100中能被3整除的数字放到一个列表中:
我的答案:

list1 = range(1,101)
list2 = [ele for ele in list1 if ele%3==0]
print(list2)
# 打印结果:
# [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]
  • 实战:0-4之间的奇数和0-5之间的偶数,构成一个元组列表如[(0,1),(0,3)…(2,3),(2,5)…]
    启示:列表推导式中的for循环可以有多个
list1 = [(i,y) for i in range(0,5) for y in range(0,6) if i%2==1 and y%2==0]
print(list1)
# 打印结果:
# [(1, 0), (1, 2), (1, 4), (3, 0), (3, 2), (3, 4)]

136.if.else的列表推导

  • 上节课的习题:由list1 = [[1,2,3],[4,5,6],[7,8,9],[1,3,5]]生成[3,6,9,5]也就是每个列表的最后一个元素。
    我的答案:
list1 = [[1,2,3],[4,5,6],[7,8,9],[1,3,5]]
list2 = [ele[2] for ele in list1]
print(list2)
  • 带有if+else的列表推导格式:
    注意基本格式:操作A if 条件A else 操作B for 变量 in 范围
dict1 = {'name': 'tom', 'salary': 5000}
dict2 = {'name': 'lucy', 'salary': 8000}
dict3 = {'name': 'jack', 'salary': 4500}
dict4 = {'name': 'lily', 'salary': 3000}
list1 = {dict1, dict2, dict3, dict4}
# 工资大于5000加200,低于5000加500
newlist = [dictx['salary']+200 if dictx['salary']>5000 else dictx['salary']+500 for dictx in list1 ]
print(newlist)
  • 问题:如何改变原来list中的内容,而不是重新创建一个新的列表?

137.生成器

  • 集合推导式:与列表推导式的基本情况一致,就是外面的[]换成{},不过要记住满足集合的条件,内部没有重复项。
  • 字典推导式:{value:key for key,value in dict1.items()}
    实战,将dict1 = {'a':'A','b':'B','c':'C'}的键值对换位置。
dict1 = {'a':'A','b':'B','c':'C'}
newlist = {value:key for key,value in dict1.items()}
  • 生成器和迭代器的引入:列表生成式可以创建列表但是在元素很多的情况下就会浪费资源,因此我们可以使用生成器根据公式计算某个位置的元素的值,这样就可以节省大量的空间,python中这种一边循环一边计算的机制,叫生成器。
  • 得到生成器的方式:①通过列表推导式得到生成器;②借助函数完成
  • 通过列表推导式得到生成器的方式:将列表生成器的外面[]换成()【由此可以从另一个角度明白为什么没有元组推导式,而且元组是不可变类型】
    g = (x*3 for i in range(10))
  • 生成器的函数:g在这里代表生成器
    g.__next__()——每调用一次,就产生一个新的下面的元素
    next(g)——系统自带的方法,产生一个下面的元素
    如果生成器已经到达尽头,生成器不能再产生元素了时候继续被调用,就会产生一个错误:StopIteration,指的是生成器已经产生元素到了尽头。
    结合昨天的异常:
g = (x*3 for i in range(10))
while True:
	try:
		e = next(g)
	except:
		break

138.生成器之函数

  • 借助函数完成生成器:①定义一个函数,函数中添加yield;②调用函数,接收调用的结果;③得到的结果就是生成器;④借助于next()__next__()得到元素。
    函数中的yieldreturn+暂停的双重含义,意思是遇到yield就会返回并暂停在当前位置,下一次调用就从上一次yield暂停的地方开始,调用一次计数一次;注意必须使用while True循环,否则每次调用的时候都会将n初始化为0,每次调用的输出都是1。
def func():
    n=0
    while True:
        n+=1
        yield n
print(next(func()))
  • 生成器的斐波那契实战:注意yieldreturn+暂停的双重含义,意思是遇到yield就会返回并暂停在当前位置,下一次调用就从上一次yield暂停的地方开始。如果生成器函数没有新的元素可以产生了,可以在生成器的函数中的return中加入提示信息(见下面的代码)。
def fib(length):
    n = 0
    a, b = 0, 1
    while n < length:
        a, b = b, a + b
        yield a
        n += 1
    return '没有更多了!'  # 当生成器走到尽头的时候会到达,并以StopIteration:'没有更多了!'的形式返回错误
g = fib(6)
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)) # StopIteration: 没有更多了!

139.生成器之方法send

  • send()
    send的第一次要使用g.send(None),每使用一个send就相当于next一下生成器;在这段代码中使用send()可以传输一个值给temp。要明确通过这种方式可以对每次循环产生不一样的结果,可以将temp在gen中再写入一些功能,这样每次调用的时候就会不一样。
def gen():
    i = 0
    while i < 5:
        temp = yield i # 将非第一次通过send传来的值给temp
        print('temp', temp)
    return '没有更多数据'
g = gen()
print(g.send(None)) # 第一次调用传输None,gen没有准备好不能传带参数的
n1 = g.send('haha') # 传输值haha
print('n1', n1)
n2 = g.send('haha')
print('n2:', n2)
  • 生成器方法汇总:
    __next__():获取下一个元素
    g.next():获取下一个元素
    g.send(value)——向生成器中传输值,第一次要使用None

140.生成器之应用多任务

  • 操作系统简介:进程>线程>协程(生成器的应用)
  • 使用生成器进行协程:使得两个函数交替运行:
    通过生成器控制函数的执行顺序,调用一次就暂停,然后再调用另一个。
def ta1(n):
    for i in range(n):
        print('No.{} person'.format(i))
        yield None

def ta2(n):
    for i in range(n):
        print('No.{} book'.format(i))
        yield None

g1 = ta1(10)
g2 = ta2(10)

while True:
    try:
        g1.__next__() # 先No.person
        g2.__next__() # 再No.book
    except:
        break
  • 总结:
    生成器的定义方式:简单的使用列表推导式;复杂的使用yield+函数。
    产生元素:next__next__()send(Value)

141.迭代器+可迭代的与生成器

  • 可迭代的对象:生成器、列表、字符串、元组、列表、字典
  • 如何判断对象可不可以迭代?isinstance(对象, Iterable),注意Iterable需要引入from collections import Iterable
from collections import Iterable
list1=[]
d = isinstance(list1, Iterable)
print(d)
  • 迭代器:迭代是访问集合元素的一种方式,迭代器是一个可以记住遍历位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被完全访问结束,迭代器只能往前不会后退。可以被next()函数调用,并不断返回下一个值的对象称为迭代器Iterator。
  • 可迭代的是不是肯定就是迭代器?列表不是迭代器但是是可迭代的。生成器是可迭代的,是迭代器。
  • 借助iter(可迭代对象)函数将可迭代的对象返回为迭代器对象。变成迭代器后可以使用next()进行使用。
list1 = [1,2,3,4]
list1 = iter(list1)
print(next(list1)) # 1
print(next(list1)) # 2
  • 迭代器是一个大的范畴,包括生成器、iter(列表)、iter(元组)、iter(字符串)等。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值