yield表达式与三元表达式以及生成式
一、叠加多个装饰器加载与运行
先定义三个装饰器:前两个为无参装饰器,后一个为有参装饰器
def deco1(func1): # func1 = wrapper2的内存地址
def wrapper1(*args,**kwargs):
print('正在运行===>deco1.wrapper1')
res1=func1(*args,**kwargs)
return res1
return wrapper1
def deco2(func2): # func2 = wrapper3的内存地址
def wrapper2(*args,**kwargs):
print('正在运行===>deco2.wrapper2')
res2=func2(*args,**kwargs)
return res2
return wrapper2
def deco3(x):
def outter3(func3): # func3=被装饰对象index函数的内存地址
def wrapper3(*args,**kwargs):
print('正在运行===>deco3.outter3.wrapper3')
res3=func3(*args,**kwargs)
return res3
return wrapper3
return outter3
加载分析:
由下而上,可以理解为就近原则,离定义原函数越近的装饰器越先加载。
@deco1 #index=outter1(wrapper2的内存地址)-->index=wrapper1的内存地址
@deco2 #index=outter2(wrapper3的内存地址)-->index=wrapper2的内存地址
@deco3(222) #-->@outter3-->index=outter3(index)-->index=wrapper3的内存地址
def index(x,y):
print(f'from index {x} {y}')
执行顺序:
自上而下的执行顺序,由远到近执行。
为了方便理解可以画一个执行流程图,即wraper1-》wrapper2-》wrapper3-》原函数
二、yield表达式
可以通过参数的形式给yield传值,yield的值可以赋值给其他变量,注意yield的值并不是等于yield后面跟的返回值
yield表达式:x=yield 返回值
使用方式一
def somebady(name):
print(f'那个谁谁谁{name}准备吃东西啦...')
while True:
# x拿到的是yield接收到的值,而不是yield后面跟的值
x = yield '我是yield后面跟的返回值哦!'
print(f'那个谁谁谁{name}吃了{x}')
g = somebady('tom')
g.send(None) # 等同于next(g)
print(g.send(None))
g.send('包子')
g.send('馒头')
g.send('饺子')
g.close()
g.send('面条') # 报错,因为关闭之后无法传值
使用方式二
def somebady(name):
food_list = []
print(f'那个谁谁谁{name}准备吃东西啦...')
while True:
# x拿到的是yield接收到的值,而不是yield后面跟的值
x = yield food_list
print(f'那个谁谁谁{name}吃了{x}')
food_list.append(x)
g = somebady('tom')
res = next(g)
print(res)
res = g.send('包子')
print(res)
res = g.send('馒头')
print(res)
res = g.send('饺子')
print(res)
g.close()
g.send('面条') # 报错,因为关闭之后无法传值
补充:
def func():
print('start.....')
x = yield 1111 # x='xxxxx'
print('哈哈哈啊哈')
print('哈哈哈啊哈')
print('哈哈哈啊哈')
print('哈哈哈啊哈')
yield 22222
g = func()
res = next(g)
print(res)
res = g.send('xxxxx')
print(res)
三、三元表达式
用一个比较两个数大小的函数引出三元表达式
def func(x,y):
if x > y:
return x
else:
return y
res=func(1,2)
print(res) #2
上述的函数的功能用三元表达式只需要一行代码就能完成
res=x if x>y else y
print(res) #2
三元表达式具体的语法格式
条件成立时要返回的值 if 条件 else 条件不成立时要返回的值
应用案例:
def func():
if 1 > 5:
print('太阳从西边出来了')
else:
print('东方红,太阳升...')
func()
# 上述函数功能用三元表达式来实现
res = '太阳从西边出来了' if 1 > 5 else '东方红,太阳升...'
print(res)
四、多种数据类型的生成式
1、列表生成式
有个存有多个名字的列表
l = ['tom_nb', 'jarry_nb', 'jack_sb', "mack_nb", 'egon']
需求一:取出名字中带有'nb'的名字
1)for循环方法
new_l=[]
for name in l:
if name.endswith('nb'):
new_l.append(name)
print(new_l) #['tom_nb', 'jarry_nb', 'mack_nb']
2)用列表生成式完成
new_l=[name for name in l if name.endswith('nb')]
print(new_l) #['tom_nb', 'jarry_nb', 'mack_nb']
补充:如果不加判断条件默认条件为True,生成跟l列表一样的列表,相当于复制了一个新的列表
new_l=[name for name in l]
print(new_l) #['tom_nb', 'jarry_nb', 'jack_sb', 'mack_nb', 'egon']
需求二:将所有小写字母变成大写
1)直接用列表生成式完成
new_l = [name.upper() for name in l]
print(new_l) #['TOM_NB', 'JARRY_NB', 'JACK_SB', 'MACK_NB', 'EGON']
需求三:将名字后面的'nb'后缀去掉
new_l=[name.replace('nb','') for name in l]
print(new_l) #['tom_', 'jarry_', 'jack_sb', 'mack_', 'egon']
通过三个需求我们将列表生成式的原理和使用方法有了一定的认识,其他数据类型的生成式也跟列表生成式类似。
2、字典生成式
keys = ['tom', 'jack', 'marry']
dic = {key: None for key in keys}
print(dic) #{'tom': None, 'jack': None, 'marry': None}
items = [('name', 'tom'), ('name', 'jack'), ('gender', 'male')]
res = {k: v for k, v in items if k != 'gender'}
print(res) #{'name': 'jack'} key重复了只保留一个键值对
3、集合生成式
keys = ['name', 'age', 'gender']
set1 = {key for key in keys}
print(set1) #{'gender', 'age', 'name'}
4、生成器表达式
g = (i for i in range(10) if i > 3)
# 此刻g内部一个值也没有
print(g, type(g))
每次必须要调用next方法才会产生一个值
print(next(g)) #4
print(next(g)) #5
print(next(g)) #6
...
5、生成打开文件所有行长度之和
方式一:
with open('笔记.txt', mode='rt', encoding='utf-8') as f:
res=0
for line in f:
res+=len(line)
print(res)
方式二:
with open('笔记.txt', mode='rt', encoding='utf-8') as f:
res=sum([len(line) for line in f])
print(res)
方式三:
with open('笔记.txt', mode='rt', encoding='utf-8') as f:
res = sum(len(line) for line in f)
print(res)