Day07 -装饰器及表达式
1.装饰器必备知识点
# *args/**kwargs
2.装饰器
2.1什么是装饰器
定义一个函数(或类),该函数是用来为其他函数的添加额外的功能
2.2 为何要用
开放封闭原则:
开放:指的是对拓展功能开放
封闭:指的是对修改源代码是封闭的
装饰器就是在不修改被装饰器对象源代码以及调用方式的前提下为被装饰对象添加新功能
3.语法糖
让你开心的语法
再被装饰对象正上方的单独一行写@装饰器名字
将原函数属性赋值给wrapper函数
from functools import wraps
import time
def timmer(func):
# func=index
@wraps(func)
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print(stop-start)
return res
return wrapper
@timmer
def index(x,y,z):
'''这是主页功能'''
time.sleep(3)
print('index %s %s'%(x,y))
return 1234565789
#源码↑
# f=index(11111,2222,33333)
# print(f)
print(help(index))
4.有参装饰器
在两层基础上再套一层,最多三层
加载顺序:自下而上
执行顺序:自上而下,但是结束是返回最后的
from functools import wraps
def auth(db_type):
def deco(func):
@wraps(func)
def wrapper(*args,**kwargs):
name=input('Ypur name:').strip()
pwd=input('Your password:').strip()
if db_type=='file':
print('基于文件验证')
with open(r'D:\pyt\学习\基础操作\user.txt','rt') as f :
for line in f:
row_name,row_pwd=line.strip().split(":")
if name==row_name and pwd==row_pwd:
print('Login successful')
res=func(*args,**kwargs)
return res
else:
print('username or password error!')
elif db_type=='mysql':
print('基于Mysql验证')
elif db_type == 'ldap':
print('基于ldap验证')
else:
print('不支持db_type')
return wrapper
return deco
@auth(db_type='file')
def index(x,y):
print('index-->>%s:%s'%(x,y))
@auth(db_type='mysql')
def home(name):
print('home->>>:%s'% name)
index(1,2)
# home('Lee')
有参装饰器模版
def 有参装饰器(x,y,z):
def outter(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
return outter
@有参装饰器(x,y,z)
def 被装饰对象(x,y):
pass
4.1装饰器案例
def deco1(func1):#func1=wrapper2的内存地址
def wrapper1(*args,**kwargs):
print('正在运行====>deco1.wrapper1')
res1 = func1(*args,**kwargs)
print('正在停止====>deco1.wrapper1')
return res1
return wrapper1
def deco2(func2):#func2=wrapper3的内存地址
def wrapper2(*args,**kwargs):
print('正在运行====>deco2.wrapper2')
res2 = func2(*args,**kwargs)
print('正在停止====>deco2.wrapper2')
return res2
return wrapper2
def deco3(x):
def outter3(func3):#func3=被装饰对象的内存地址
def wrapper3(*args,**kwargs):
print('正在运行====>deco3.wrapper3')
res3 = func3(*args,**kwargs)
print('正在停止====>deco3.wrapper3')
return res3
return wrapper3
return outter3
#加载顺序自下而上
@deco1
@deco2
@deco3(111)
def index(x,y):
print('index is %s :%s '%(x,y))
index(1,2)
#结果
>>>正在运行====>deco1.wrapper1
>>>正在运行====>deco2.wrapper2
>>>正在运行====>deco3.wrapper3
>>>index is 1 :2
>>>正在停止====>deco3.wrapper3
>>>正在停止====>deco2.wrapper2
>>>正在停止====>deco1.wrapper1
5.迭代器
迭代取值的工具,迭代是重复的过程,每次重复都是基于上一次的结果,而不是单纯的重复
#调用可迭代对象的__iter__会将其转成迭代器对象
d={'a':1,'b':2,'c':3}
res=d.__iter__()
#d.__iter__ <==> iter(d)
print(res)#迭代器对象<dict_keyiterator object at 0x00000194E3827E00>
#不通过索引取值
res.__next__()
#超出字典的取值会抛出异常(StopIteration)
#对同一个迭代器取值,在取净后,在对其取值取不到。
while True:
try:
print(res.__next__())
except StopIteration:
break
5.1可迭代对象与迭代器对象详解
可迭代对象(可以转换成迭代器的对象):但凡内置有" iter " 方法的都称为可迭代对象
- 可迭代对象.——iter——():得到迭代器对象
迭代器对象:内置有“——next——”并且内置有“——iter——”方法的对象
-
迭代器对象.——next——():得到迭代器下一个值
-
迭代器对象.——iter——():得到迭代器本身(调了和没调一样,都是自己,是为了让for循环统一起来)
可迭代对象:字符串、列表、元组、字典、集合、打开的文件
迭代器对象:打开的文件
5.2 for循环的工作原理
for循环可以称之为迭代器循环
d={'a':1,'b':2,'c':3}
#1.调用d.__iter__()得到一个迭代器对象
#2.迭代器对象.__next__()拿到一个返回值,然后把返回值赋值给k
#3.循环往复步骤2,直到抛出StopIteration异常,for循环会捕捉异常然后结束循环
for k in d:
print(k)
#相当于
d={'a':1,'b':2,'c':3}
res=d.__iter__()
while True:
try:
print(res.__next__())
except StopIteration:
break
5.3 迭代器优缺点总结
优点1:既能循环有索引,又能循环没有索引的对象
优点2:更加节省内存,惰性计算
缺点1:取值不如索引方便
缺点2:有生命周期
6. 自定义迭代器——生成器
#yield返回多个值
#如何得到自定义的迭代器:
#在函数体内存在yield关键字,调用函数并不会执行函数体代码
#会返回一个生成器对象,生成器即迭代器
def func():
print('第一次')
yield 1
print('第二次')
yield 2
print('第三次')
yield 3
#生成器就是迭代器
res=func()#<generator object func at 0x00000295397E16D0>
#会触发函数体代码的运行,遇到yield停下来,将yield后的值当做本次调用的结果返回
res.__next__()#第一次
print(res.__next__())#第一次 1
6.1 yield表达式
#yield 返回值
def dog(name):
print('刀哥%s准备吃东西拉'%name)
while True:
#x拿到的是yield接受到的值,不是返回值
x=yield None
print('刀哥%s吃了%s'%(name,x))
g=dog('alex')
g.send(None)#等同于next(g)
#会进行挂起
g.send('a bone')#在next的基础上加了传值功能
g.send('a sex')#在next的基础上加了传值功能
g.close()#关闭后不可传值
综合性应用
def dog(name):
print('刀哥%s准备吃东西拉'%name)
food_list=[]
while True:
#x拿到的是yield接受到的值,不是返回值
x=yield food_list
print('刀哥%s吃了%s'%(name,x))
food_list.append(x)
g=dog('alex')
res=g.send(None)#初始化
print(res) #[]
res=g.send('a bone')#相当于x='a bone'
print(res) #['a bone']
res=g.send('a sex')
print(res) #['a bone','a sex']
7.三元表达式
语法格式:条件成立时返回的值 if 条件 else 条件不成立时返回的值
#比较大小(太麻烦)
def func(x,y):
if x>y:
return x
elif x<y:
return y
else:
return 'Equal'
#三元表达式
res= x if x>y else y
8.列表生成式
l=['alex_dsb','lxx_dsb','wxx_dsb','xxq_dsb','egon']
# new_l=[]
# for i in l :
# if 'dsb' in i :
# new_l.append(i)
new_l=[i for i in l if 'dsb' in i]#代替上述代码
#把所有小写字母变成大写
#把所有名字的后缀_dsb去掉
#方案一
new_l=[i.upper() for i in l ]
#方案二
new_l=[i.replace('_dsb','') for i in l ]
9.其他生成式
#字典生成式
items=[('name','egon'),('age',18),('gender','male')]
dic={k:v for k,v in items if k!='gender'}
print(dic)
#集合生成式
keys=['name','age','gender']
dic={key for key in keys}
print(dic,type(dic))
#生成器生成式
t=(i for i in range(10) if i>3)#此时内部一个值也没有
print(next(t))
print(next(t))
print(next(t))
###################################
res=0
with open(r'D:\pyt\学习\python笔记\函数.md','rt',encoding='utf-8') as f:
for line in f :
res+=len(line)
print(res)#2735
with open (r'D:\pyt\学习\python笔记\函数.md','rt',encoding='utf-8') as f:
# res= sum([len(line) for line in f])
res= sum(len(line) for line in f)
print(res)