装饰器
装饰器定义:本质就是函数,功能是为其他函数添加新功能
1.不修改被装饰函数的源代码(开放封闭原则)
2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式
装饰器=高阶函数+函数嵌套+闭包
高阶函数定义:
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
例1:一个计算函数运行时间的装饰器(装饰器中无参数)
import time
def timer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs) #调用以参数形式传入的函数
stop_time=time.time()
print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
return res
return wrapper
@timer #@timer就等同于cal=timer(cal)=wrapper
def cal(array):
res=0
for i in array:
res+=i
return res
print(cal(range(100000))) #-->wrapper(range(1000)) -->res=cal(range(1000))
只要记住 @装饰器 就相当于 obj = 装饰器(obj) 这里的obj为被装饰的类
例2:一个登入的例子(装饰器中带有参数)
user_list=[
{'name':'alex','passwd':'123'},
{'name':'linhaifeng','passwd':'123'}, #定义一个已经存在的用户表
{'name':'wupeiqi','passwd':'123'},
{'name':'yuanhao','passwd':'123'},
]
current_user={'username':None,'login':False} #判断用户是否已经登入
def auth(auth_type='file'):
def auth_deco(func):
def wrapper(*args,**kwargs):
if auth_type == 'file': #判断用户的类型
if current_user['username'] and current_user['login']:#判断用户是否登入
res=func(*args,**kwargs)
return res
username=input('用户名: ').strip()
passwd=input('密码: ').strip()
for index,user_dic in enumerate(user_list): #验证用户信息
if username == user_dic['name'] and passwd == user_dic['passwd']:
current_user['username']=username #保存登入状态
current_user['login']=True
res=func(*args,**kwargs)
return res
break
else: #信息错误
print('用户名或者密码错误,重新登录')
elif auth_type == 'ldap': #如果用户类型是'ldap',直接登入
print('巴拉巴拉小魔仙')
res=func(*args,**kwargs)
return res
return wrapper
return auth_deco
#auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
#就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
@auth(auth_type='file') #-->@auth_deco -->index=auth(index)=wrapper -->index()相当于wrapper()
def index():
print('欢迎来到主页面')
@auth(auth_type='ldap')
def home():
print('这里是你家')
def shopping_car():
print('查看购物车啊亲')
@auth(auth_type='file')
def order():
print('查看订单啊亲')
index()
登入页面判断用户是否登入,如果用户的类型是'ldap',直接登入.如果用户类型是'file',判断用户是否是登入状态,没有登入的话进行验证,验证通过之后将该用户保存为登入状态,下次进入其他页面不用登入.
装饰器的作用是在不改变函数的情况下为函数添加新的功能.
类中也有类似的方法,可以通过继承的方式来给已经定义了的类添加新的属性.
class animal:
print('run')
class cat(animal):
def __init__(self,name):
self.name = name
c1 = cat('ll') #会先调用父类的属性,在调用子类的,如果继承多个类,调用顺序从左往右