装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则1 不修改被装饰对象的源代码。 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
装饰器需要的知识储备为:高阶函数+函数嵌套+闭包
import time
#装饰器的框架
def timer(func):
print(func)
def wrapper(*args,**kwargs):
starttime = time.time()
func() #func()<==>test()
stoptime = time.time()
print("函数运行时间为 %s" % (stoptime-starttime))
return wrapper
@timer #test = timer(test) timer(test)返回的是wrapper的地址,所以test<==>wrapper
def test():
time.sleep(3)
print("程序已经运行完毕")
test()
加上返回值和参数
def timer(func): print(func) def wrapper(*args,**kwargs): starttime = time.time() res = func("张三",18) #func()<==>test() stoptime = time.time() print("函数运行时间为 %s" % (stoptime-starttime)) return res return wrapper @timer #test = timer(test) timer(test)返回的是wrapper的地址,所以test<==>wrapper def test(name,age): time.sleep(3) print("程序已经运行完毕,姓名是%s,年龄为%s " % (name, age)) return "这是test的返回值" res = test() print(res)
- 登录功能
- 函数里加上了统计时间的功能
- 模拟登录京东首页
import datetime
def test(func):
def wrapper():
name = input("请输入姓名:")
now_time = datetime.datetime.now()
print("尊敬的%s先生,现在时间为%s" % (name, now_time))
res = func()
return res
return wrapper
@test # index = test(index)
def index():
print("欢迎来到京东主页")
- 登录+认证功能
- 用的一个很有用的知识点,通过用全局变量,保存登录的状态,代码中有清楚的表示,
- 下面的代码用的是有参数的装饰器,参数用来表示登录的认证类型(可以通过下面的代码了解带参装饰器的用法)
# 具有认证功能
# 只需要登陆一次,可保存登陆状态
# 全局变量(检测登陆状态)
func_auth = {'user': None, 'login': False}
def test_auth(auth_type='file'):
def test(func):
def wrapper():
print("认证类型是:", auth_type)
auth_dict = {'alex': 123, "段亚运": 123, 'lin': 123}
if auth_type == "file":
# 判断当前是否为登陆状态
if func_auth['user'] and func_auth['login']:
print("当前为登陆状态")
res = func()
return res
name = input("请输入用户名:")
password = input("请输入密码:")
print("尊敬的%s先生," % name)
# 切记input()得出的结果是"str"
if auth_dict[name] == eval(password):
#print("第一次登陆成功")
func_auth['user'] = name
func_auth['login'] = True
res = func()
return res
elif auth_type == 'mongodb':
print("认证方式不正确")
return wrapper
return test
@test_auth(auth_type="file") # index = test(index)
def index():
print("欢迎来到京东主页")
@test_auth(auth_type="mongodb")
def home():
print("欢迎进入您的个人中心")
index()
home()
下面这个代码是复制的老男孩教育中,linhaifeng老师博客中的一段关于
登录一次后会保存状态,但是保存的时间有限定,超时后须重新登录(方法不难,不过感觉实现的不是特别好,仅供参考)
# 编写装饰器,为多个函数加上认证功能,要求登录成功一次,
# 在超时时间内无需重复登录,超过了超时时间,则必须重新登录
# 全局变量(检测登陆状态)
import time
import random
user = {'user': None, 'login_time': None, 'timeout': 0.000003}
def timmer(func):
def wrapper(*args, **kwargs):
s1 = time.time()
res = func(*args, **kwargs)
s2 = time.time()
print('%s' % (s2 - s1))
return res
return wrapper
def auth(func):
def wrapper(*args, **kwargs):
if user['user']:
timeout = time.time() - user['login_time']
if timeout < user['timeout']:
return func(*args, **kwargs)
name = input('name>>: ').strip()
password = input('password>>: ').strip()
if name == 'egon' and password == '123':
user['user'] = name
user['login_time'] = time.time()
res = func(*args, **kwargs)
return res
return wrapper
@auth
def index():
time.sleep(random.randrange(3))
print('welcome to index')
@auth
def home(name ):
time.sleep(random.randrange(3))
print('welcome %s to home ' % name)
index()
home('egon')