day14 生成器/ 表达式形式yield的应用/三元表达式与列表推导式/字典生成式/杂项

时间:2022-12-23 23:31:07

生成器:函数内包含有yield的关键字,再调用函数,就不会执行函数体代码,拿到的返回值就是一个生成器对象

def chicken():
print('first======>')
yield 1
print('second======>')
yield 2
print('third======>')
yield 3

res=chicken()
#生成器本质就是迭代器,也就是说生成器的玩法,就是迭代器的玩法
# print(res) #得到一个生成器对象
res.__next__() #first======>
res.__next__() #second=====>
res.__next__() #third======>

得到返回值

def chicken():
    print('first======>')
    yield 1
    print('second======>')
    yield 2
    print('third======>')
    yield 3

obj=chicken()

res=obj.__next__()                    
print(res)                            
res=obj.__next__()                    
print(res)             
res=obj.__next__()     #每次next取的是yield后面的值               
print(res)

# first======>    #next就能取值,取的是函数的返回值
# 1
# second======>  下一次next基于上一次暂停的位置往下走
# 2
# third======>
# 3

 

for循环的迭代原理

# for循环原理
def chicken():
    print('========>first')
    yield   1
    print('========>second')
    yield   2
    print('========>third')
    yield   3
obj=chicken()
#1、iter_obj=obj.__iter__(),拿到迭代器
#2、触发iter_obj.__next__(),拿到该方法的返回值,赋值给 item
#3、周而复始,直到函数内不再有yield,即取值完毕
#4、for会检测到StopIteration结束循环 for item in obj:#obj是可迭代对象 obj.__iter__() print(item)

总结yield:

#1、为我们提供了一种自定义迭代器的方式

#2、可以在函数内用yield的关键字,调用函数拿到的结果就是一个生成器,生成器就是迭代器,yield可以像return一样用于返回值,区别return只能返回一次值

而yield 可以返回多次值   yield可以保存函数的执行状态

def my_range():
    print('start....')
    n=0
    while True:
        yield n
        n+=1
obj=my_range()
print(obj)  #生存器的内存地址

print(obj.__next__())
print(obj.__next__())
print(obj.__next__())

 

def my_range(start,stop,step):
    n=start
    while n<stop:
        yield n
        n+=step

obj=my_range(3,7,2)
print(obj.__next__())
print(obj.__next__())

for item in my_range(5,10,2)
  print(item)

 表达式形式yield的应用

def eat(name):
    print('%s ready to eat'%name)
    food_list=[]
    while True:
        print('我草靠日')
        food=yield food_list#food='骨头
        food_list.append(food)#food='泔水',循环一次停在yield
        print('%s start to eat%s'%(name,food))

dog1=eat('alex')

#1、 必须初始化一次,让函数停在yield的位置
dog1.__next__()

#2、接下来的事,就是喂狗
#send有两方面的功能
# 1、给yield传值
# 2、同__next__的功能
res1=dog1.send('泔水')#传值 #传多个值要放能存多个值的数据类型里面
print(res1)
res2=dog1.send('骨头')
print(res2)
res3=dog1.send('shit')
print(res3)

 

三元表达式与列表推导式

三元表达式
条件成立时的返回值 if 条件else不成立的返回值

def max(x,y):
    if x> y:
        return x
    else:
        return y
x=10
y=20

res=x if x>y else y
print(res)

三元哪三元呢 中间x>y条件算一元 条件成立的返回值算一元(x) 右边条件成立的返回值算一元(y)

 

#列表生成式

l=[]

for i in range(1,11)

names=['alex','wxx','lxx']
l=[]
for name in names:
    l.append(name+'SB')
print(l)

# 可以简写成
names=[name+'SB' for name in names]
print(names)

 

列表生成式子

l=[item**2 for item in range(1,11)]
print(l)

 

names=['alex','wxx','egon','lxx','zhangmingyan']
# l=[]
# for name in names:
#     if name != 'egon':
#         l.append(name + 'SB')
# names=l
names=[name+'SB' for name in names if name != 'egon'] #列表式可以这么表示
print(names)  

语法:[expression for iteml in iterable1 if conditionl]

列表生成式的目的是更方便的造列表

列表生成式只能for if ......for if 不能跟else

错误:l=[item**2 for item in range(1,5) if item>2 else]

 

 

 

字典生成式

s1='hello'
l1=[1,2,3,4,5]
res=zip(s1,l1)
# print(res)  #<zip object at 0x00000000021BBEC8>
print(list(res))#[('h', 1), ('e', 2), ('l', 3), ('l', 4), ('o', 5)]

keys=['name','age','sex']
values=['egon',18,'male']
res=zip(keys,values)
print(res)
print(list(res))
print(list(res))  #这里迭代器为什么只可以取值一次
d={}
for k,v in res:
    d[k]=v
print(d)

info={'name':'egon','age':18,'sex':'male'}

keys=info.keys()
print(keys)
values=info.values()
print(values)




再把keys和values转回原来的字典
d={k:v for k,v in zip(keys,values)}
print(d)

 

杂项

t=(i for i in rang(10))
print(t)   #花括号字典,中括号列表 小括号不是元祖

#<generator object <genexpr> at 0x00000000020CFCA8>

生成器好处省内存

生成器表达式
g=(i for i in range(10))
# print(g)

print(next(g))
print(next(g))

 

with open('a.txt',encoding='utf-8') as f:      #生成器表达式
    nums=[len(line) for line in f]             # g=(i for i in range(10))
    # nums=(len(line) for line in f)
    print(max(nums))                #对于生成器表达式来说你造出来那生成器开始没有执行任何代码 直到next才刚刚执行一行代码
print(max(nums))
print(max(nums))



l=['egg%s' %i for i in range(100)]
print(l)

g=('egg%s' %i for i in range(1000000000000))
# print(g)
print(next(g))
print(next(g))

列表生成式相当于直接给了一筐鸡蛋,而生成器表达式,直接给了一只鸡,
只鸡可以无限的下蛋,同一时间只有一个鸡蛋,先拉先吃,而列表要来一个真正的空间存进去

 

  

今日作业

今日作业:
	1、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?
	2、思考题
		with open('a.txt',encoding='utf-8') as f:
			g=(len(line) for line in f)
		print(sum(g))

	3、文件shopping.txt内容如下
		mac,2000,3
		lenovo,3000,10
		tesla,1000000,10
		chicken,200,1

		求总共花了多少钱?
		打印出所有的商品信息,格式为
		[{'name':'xxx','price':'3333','count':3},....]
		求单价大于10000的商品信息,格式同上

	4、文件内容如下,标题为:姓名,性别,年纪,薪资
		egon male 18 3000
		alex male 38 30000
		wupeiqi female 28 20000
		yuanhao female 28 10000

		要求:
		从文件中取出每一条记录放入列表中,
		列表的每个元素都是{'name':'egon','sex':'male','age':18,'salary':3000}的形式

	5 根据1得到的列表,取出薪资最高的人的信息
	6 根据1得到的列表,取出最年轻的人的信息
	7 根据1得到的列表,将每个人的信息中的名字映射成首字母大写的形式
	8 根据1得到的列表,过滤掉名字以a开头的人的信息