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)
posted @ 2020-03-25 19:03  风起千寻  阅读(196)  评论(0编辑  收藏  举报