一、叠加多个装饰器的加载、运行分析
加载顺序自下而上(自内向外)
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
分析:
-
执行@deco3(111),相当于执行了deco3中的outter函数,这一步实质上就是index = outter3(index)。 此刻,func3 = 被装饰对象index函数的内存地址,执行完毕后返回wrapper3,则现在原函数名index = wrapper3的内存地址。
-
接下来执行@deco2,相当于执行index = deco2(wrapper3的内存地址)。 此刻,func2 = wrapper3的内存地址,执行完毕后返回wrapper2,则现在原函数名index = wrapper2的内存地址。
-
接下来执行@deco1,相当于执行index = deco1(wrapper2的内存地址)。 此刻,func1 = wrapper2的内存地址,执行完毕后返回wrapper1,则现在原函数名index = wrapper1的内存地址。
执行顺序自上而下(自外向内)
执行顺序的实质就是wrapper的运行顺序
分析:
-
加载完之后,index = wrapper1的内存地址,故此刻执行index(1, 2),实质上是执行wrapper1(1, 2)。
-
而wrapper1()中的func1(),func1此刻是wrapper2的内存地址,实质上是执行wrapper2(1, 2)。
-
而wrapper2()中的func2(),func2此刻是wrapper3的内存地址,实质上是执行wrapper3(1, 2)。
-
来到wrapper3(),wrapper3()内的func3此刻是被装饰对象index函数的内存地址,实质上是执行原函数index(1, 2)。
-
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默认为生成器表达式。