date: 2021-06-12title: Python装饰器 #标题
tags: python #标签
categories: python # 分类

记录下python装饰器的代码格式。参考:

这里只是简单记录下代码,如果想研究装饰器具体原理,可以参考上面两个链接。

装饰器基础代码

  1. '''
  2. timmer作为一个装饰器
  3. @timmer 被称之为语法糖
  4. 想要哪个函数使用定义好的装饰器
  5. 只需在对应的函数上一行写上语法糖即可
  6. 下面的代码是实现计算某个函数的执行效率
  7. '''
  8. import time
  9. # 定义装饰器函数
  10. def timmer(f):
  11. def inner():
  12. start_time = time.time()
  13. f()
  14. end_time = time.time()
  15. print(f'代码运行时间为{end_time - start_time}秒')
  16. return inner
  17. @timmer # 此语法糖等同于 bokeyuan=timmer(bokeyuan)
  18. def bokeyuan():
  19. time.sleep(2)
  20. print('欢迎登录博客园首页')
  21. @timmer # 此语法糖等同于 houtai=timmer(houtai)
  22. def houtai():
  23. time.sleep(3)
  24. print('欢迎登录博客园后台')
  25. bokeyuan()
  26. houtai()

装饰器带返回值

  1. import time
  2. def timmer(f):
  3. def inner():
  4. start_time = time.time()
  5. ret = f() # 定义变量接受函数的返回值
  6. end_time = time.time()
  7. print(f'代码运行时间为{end_time - start_time}秒。')
  8. return ret # 将真正函数的返回值返回给调用者
  9. return inner
  10. @timmer
  11. def index():
  12. time.sleep(2)
  13. print('欢迎登录博客园...')
  14. return 666
  15. print(index())
  16. # 输出结果如下:
  17. 欢迎登录博客园...
  18. 代码运行时间为2.000514268875122秒。
  19. 666

带参数的装饰器

  1. import time
  2. def timmer(f):
  3. def inner(*args, **kwargs): # 1、inner函数接收参数
  4. start_time = time.time()
  5. ret = f(*args, **kwargs) # 2、然后传递给真正的函数
  6. end_time = time.time()
  7. print(f'代码运行时间为{end_time - start_time}秒。')
  8. return ret
  9. return inner
  10. @timmer
  11. def index(name, age):
  12. time.sleep(2)
  13. print(f'欢迎{age}岁的{name}登录博客园...')
  14. return 666
  15. index(name='lvjianzhao', age=18)

规范的装饰器代码

  1. def zsq(f):
  2. def inner(*args, **kwargs):
  3. # 执行真正函数之前要做的事
  4. ret = f(*args, **kwargs) # 执行真正的函数
  5. # 执行真正函数之后要做的事
  6. return ret
  7. return inner
  8. @zsq
  9. def login(name, age):
  10. print(f'欢迎{age}岁的{name}登录。')
  11. login(name='吕建钊', age=18)

模仿登录验证页面

  1. userlist = {'zhangsan': '123.com'}
  2. status_dict = {
  3. 'username': None,
  4. 'status': False
  5. }
  6. def login():
  7. conut = 0
  8. while conut < 3:
  9. conut += 1
  10. name = input('请输入用户名:').strip()
  11. passwd = input('请输入密码:').strip()
  12. if name in userlist and passwd == userlist[name]:
  13. status_dict['username'] = name
  14. status_dict['status'] = True
  15. return '登录成功'
  16. else:
  17. print('用户名或密码错误,请重新输入!')
  18. continue
  19. else:
  20. print('登录次数超过三次,请稍后再试!')
  21. exit(1)
  22. def auth(f):
  23. def inner(*args, **kwargs):
  24. if status_dict['status']:
  25. ret = f(*args, **kwargs)
  26. return ret
  27. else:
  28. login()
  29. if status_dict['status']:
  30. ret = f(*args, **kwargs)
  31. return ret
  32. return '登录失败'
  33. return inner
  34. @auth
  35. def index():
  36. print('欢迎访问博客首页')
  37. @auth
  38. def comment():
  39. print('欢迎访问评论页面')
  40. @auth
  41. def rili():
  42. print(f'欢迎访问日历页面,当前用户为;{status_dict["username"]}')
  43. index()
  44. comment()
  45. rili()

带参数的装饰器2

原理讲解起来有点多,建议观看 老男孩视频:带参数的装饰器 来理解。

# 带参数的装饰器基础代码规范
def logger(path):
    def log(func):
        def inner(*args, **kwargs):
            # 函数执行前要做的事情
            # pass
            # 执行真正的函数
            # ret=func(*args,**kwargs)
            # 函数执行后要做的事情
            # pass
            # return ret
        return inner
    return log

下面是一个简单的功能,装饰器的功能是打印日志,但多了一个功能就是将不同函数的日志打印到不同文件中。

import time

# 比起之前的装饰器,又多了一层,以便将日志路径设置为自由变量
def logger(path):   
    def log(func):
        def inner(*args, **kwargs):
            ret = func(*args, **kwargs)
            with open(path, encoding='utf-8', mode='a+') as f:
                f.write(f'{time.strftime("%Y-%m-%d %H:%M:%S")} 调用了{func.__name__} 函数')

        return inner

    return log


@logger(r'C:\Users\Administrator\Desktop\auth.log')  # 这里将日志路径给传参到装饰器中
def auth():
    print('登录成功!')


@logger(r'C:\Users\Administrator\Desktop\registry.log')  # 这里将日志路径给传参到装饰器中
def registry():
    print('注册成功!')


auth()
registry()