Python学习_基础_16_叠加多个装饰器的加载与运行分析、三元表达式、列表/字典/集合生成式、生成器表达式

本文深入解析Python装饰器的加载与运行机制,通过实例详细阐述装饰器的叠加执行过程。同时,介绍了三元表达式、列表生成式、字典生成式和集合生成式等代码简化技巧,并展示了生成器表达式在统计文件字符数量中的应用。通过这些内容,旨在提升代码的简洁性和效率。
摘要由CSDN通过智能技术生成

一、叠加多个装饰器的加载、运行分析

加载顺序自下而上(自内向外)

def deco1(func1):
    def wrapper1(*args, **kwargs):
        print('正在运行===>deco1.wrapper1')
        res1 = func1(*args, **kwargs)
        return res1

    return wrapper1


def deco2(func2):
    def wrapper2(*args, **kwargs):
        print('正在运行===>deco2.wrapper2')
        res2 = func2(*args, **kwargs)
        return res2

    return wrapper2


def deco3(x):
    def outter3(func3):
        def wrapper3(*args, **kwargs):
            print('正在运行===>deco3.outter3.wrapper3')
            res3 = func3(*args, **kwargs)
            return res3

        return wrapper3

    return outter3


@deco1
@deco2
@deco3(111)
def index(x, y):
    print('from index %s:%s' % (x, y))


index(1, 2)
# 运行结果:
# 正在运行===>deco1.wrapper1
# 正在运行===>deco2.wrapper2
# 正在运行===>deco3.outter3.wrapper3
# from index 1:2
分析:
  1. 执行@deco3(111),相当于执行了deco3中的outter函数,这一步实质上就是index = outter3(index)。
    此刻,func3 = 被装饰对象index函数的内存地址,执行完毕后返回wrapper3,则现在原函数名index = wrapper3的内存地址。
    
  2. 接下来执行@deco2,相当于执行index = deco2(wrapper3的内存地址)。
    此刻,func2 = wrapper3的内存地址,执行完毕后返回wrapper2,则现在原函数名index = wrapper2的内存地址。
    
  3. 接下来执行@deco1,相当于执行index = deco1(wrapper2的内存地址)。
    此刻,func1 = wrapper2的内存地址,执行完毕后返回wrapper1,则现在原函数名index = wrapper1的内存地址。
    

执行顺序自上而下(自外向内)

执行顺序的实质就是wrapper的运行顺序
分析:
  1. 加载完之后,index = wrapper1的内存地址,故此刻执行index(1, 2),实质上是执行wrapper1(1, 2)
  2. 而wrapper1()中的func1(),func1此刻是wrapper2的内存地址,实质上是执行wrapper2(1, 2)
  3. 而wrapper2()中的func2(),func2此刻是wrapper3的内存地址,实质上是执行wrapper3(1, 2)
  4. 来到wrapper3(),wrapper3()内的func3此刻是被装饰对象index函数的内存地址,实质上是执行原函数index(1, 2)
  5. index函数执行结束之后,也就是func3()执行结束,wrapper3()执行结束。
    紧跟着wrapper2()执行结束。
    再然后wrapper1()执行结束。
    

在这里插入图片描述

二、三元表达式(精简代码)

语法格式: 条件成立时要返回的值+if+条件+else+条件不成立时要返回的值
def func1(x, y):
    if x > y:
        return x
    else:
        return y


def func2(x, y):
    return x if x > y else y
x = 1
y = 2

res = 'x大' if x > y else 'y大'
print(res)
z = 10 if 10 > 2 else 2
print('{}比较大'.format(z))  # 10比较大

三、列表生成式(精简代码)

提取列表中以“老师”结尾的字符串,并组成新列表。

l = ['张三老师', '李四老师', '山炮同学', "王五老师", 'me']
new_l = []
for name in l:
    if name.endswith('老师'):
        new_l.append(name)

print(new_l)  # ['张三老师', '李四老师', '王五老师']

使用列表生成式直接生成,循环遍历l列表的元素,赋值给name,如果name以老师结尾则放入新列表。

l = ['张三老师', '李四老师', '山炮同学', "王五老师", 'me']
new_l = [name for name in l if name.endswith('老师')]
print(new_l)  # ['张三老师', '李四老师', '王五老师']

如果不加条件则是全部都放入新列表

l = ['张三老师', '李四老师', '山炮同学', "王五老师", 'me']
new_l = [name for name in l]
print(new_l)  # ['张三老师', '李四老师', '山炮同学', '王五老师', 'me']

同样的,写其他功能的列表生成式:

l = ['张三老师', '李四老师', '山炮同学', "王五老师", 'me']

# 把所有小写字母全变成大写
new_l = [name.upper() for name in l]
print(new_l)  # ['张三老师', '李四老师', '山炮同学', '王五老师', 'ME']

# 把所有的名字去掉老师后缀
new_l = [name.replace('老师', '') for name in l]
print(new_l)  # ['张三', '李四', '山炮同学', '王五', 'me']

四、其他生成式(精简代码)

字典生成式

keys = ['name', 'age', 'gender']
dic = {key: None for key in keys}
print(dic)  # {'name': None, 'age': None, 'gender': None}

items = [('name', 'egon'), ('age', 18), ('gender', 'male')]
res = {k: v for k, v in items if k != 'gender'}
print(res)  # {'name': 'egon', 'age': 18}

集合生成式

keys = ['name', 'age', 'gender']

set1 = {key for key in keys}  # 跟字典生成式的区别在于这里是key不是key:value
print(set1)  # {'name', 'age', 'gender'}
print(type(set1))  # <class 'set'>

没有元组生成式,因为元组不可更改

生成器表达式

g = (i for i in range(10) if i > 3)
# !!!!!!!!!!!强调!!!!!!!!!!!!!!!
# 此刻g内部一个值也没有

print(g, type(g))
# <generator object <genexpr> at 0x00000215558FB970> <class 'generator'>

print(next(g))  # 4
print(next(g))  # 5
print(next(g))  # 6
print(next(g))  # 7
print(next(g))  # 8
print(next(g))  # 9
# print(next(g))#StopIteration异常

利用生成式统计文件内字符个数

# 方式一:常规方法
with open('a.txt', mode='rt', encoding='utf-8') as f:
    res = 0
    for line in f:
        res += len(line)
    print(res)
    

print(sum([1, 2, 3, 4, 5]))  # 15  sum()内要是可迭代对象
# 方式二:列表生成式 + sum(可迭代对象)
with open('a.txt', mode='rt', encoding='utf-8') as f:
    lineSize = [len(line) for line in f]
    res = sum(lineSize)
    print(res)
    
    
# 方式三:生成器表达式 + sum(可迭代对象)
with open('a.txt', mode='rt', encoding='utf-8') as f:
    g = (len(line) for line in f)
    res = sum(g)
sum((len(line) for line in f))
# 可简写为以下形式
sum(len(line) for line in f)

# 二者结果相同,len(line) for line in f不加括号python默认为生成器表达式。
('a.txt', mode='rt', encoding='utf-8') as f:
    g = (len(line) for line in f)
    res = sum(g)
sum((len(line) for line in f))
# 可简写为以下形式
sum(len(line) for line in f)

# 二者结果相同,len(line) for line in f不加括号python默认为生成器表达式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值