Python学习笔记-装饰器

装饰器

装饰器 decorator

1. 功能

  1. 引入日志

  2. 函数执行时间统计

  3. 执行函数前预备处理

  4. 执行函数后清理功能

  5. 权限校验等场景

  6. 缓存

2. 原则

定义函数遵循 闭包 的原则,函数 作为 参数

def dec_func(f):   # 装饰器函数:闭包+函数作为参数
	def check():
        f()
    return check
# 使用装饰器函数
# 1.调用dec_func函数 2.执行函数体中内容 3.加载内层函数 
# 4.返回内层函数 5.将返回的内层函数给func赋值 (func = check)
@dec_func
def func ():      # 功能函数
    print('hello')

如果被装饰的 功能函数有返回值,那么 装饰器函数 也一定要 有返回值

user_list = {'zhangsan': 'z0001', 'lisi': 'l0001', '1': '1'}

def login():
    user_name = input('请输入用户名:')
    password = input('请输入密码:')
    r = check_login(user_name, password)
    return r

@dec_login
def check_login(user_name, password):   # 被装饰的功能函数有返回值
    if user_name in user_list:
        if user_list[user_name] == password:
            return True   # 用户名与密码均正确,返回True
        else:
            return False  # 用户名正确但密码错误,返回False
    else:
        return False      # 用户名错误,返回False
    pass

def dec_login(func):
    def wrapper(*args, **kwargs):
        print('登录验证中')
        r = func(*args,**kwargs)  # 接收原函数的返回值
        if r:
            print('r is true')    # 返回值是True,打印 'r is true'
            return True           # 返回True
        else:
            print('r is false')   # 返回值是False,打印'r is false'
            return False          # 返回False
    return wrapper

res = login()
print(res)

3. 实质

函数间调用:在内层函数里调用外部的功能函数

函数名的互相赋值:对于使用者来说调用的还是原来的功能函数,实质上在底层执行的是装饰器的内层函数。

4. 装饰器带参数

def 装饰器名(装饰器参数):
	# 使用装饰器参数
    def second(func):
        def third(函数参数):
            res = func(函数参数)
            return res 
        return third
    # 使用装饰器参数
    return second
def dec_func(a,b):  # 定义装饰器
    print(a,b)      # 使用装饰器参数
    def dec_second(func):
        def dec_third(a,b):
            res = func(a,b)
            res += 1
            return res
        return dec_third
    return dec_second
@dec_func(1,2)   # 装饰,并给出装饰器参数
def func(a,b):
    return a+b
print(func(1,2))
==========================
1 2
4

5. 多层装饰器

谁离原函数最近先执行哪个装饰器,将第一层装饰器的返回结果传给第二层装饰器

最终原函数得到的地址是第二层装饰器的返回值wrapper的地址

def dec1(func):
    def wrapper(*args,**kwargs):
        func(*args,**kwargs)
        print('装饰器1')
        pass
    return warpper

def dec2(func):
    def wrapper(*args,**kwargs):
        func(*args,**kwargs)
        print('装饰器2')
        pass
    return wrapper

@dec2  # 后执行的装饰器
@dec1  # 先执行的装饰器
def func1():
    print('功能函数')
    return

func1()
====================
功能函数
装饰器1
装饰器2

6. 类装饰器

定义一个类作为装饰器来装饰方法

class Decorator:
    def __init__(self,func):
        self.func = func
    def __call__(self,*args,**kwargs):
        # 装饰内容
        self.func(*args,**kwargs)
        # 装饰内容
@Decorator
def func(a,b):
    print(a+b)

7. 举例

这是一个验证码的例子

import random
# 从字符表中随机抽取指定位数组成验证码
def generator_code(length):
    code = ''
    ss = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMzxcvbnmasdfghjklpoiuytrewq'
    for i in range(length):
        ran = random.choice(ss)
        code += ran
        pass
    print("本次的验证码为:", code)
    pass

现在要求在生成验证码之前,校验权限码。权限码正确,输出生成的验证码;权限码错误,输出错误提示。利用装饰器完成

import random
# 装饰器代码,实现权限码验证
def genc_check(func):  # 此处func传入功能函数-->func = generator_code
    def inner_genc_check(*args,**kwargs):   # 利用可变参数保证通用性
        flag = input('确认使用权限:')
        if flag == '0070270':   # 判断使用权限,正确则调用功能函数
            func(*args,**kwargs)   # 调用功能函数并传入实参
        else:
            print('权限验证失败!')
            pass
        pass
    return inner_genc_check
@genc_check     # 利用装饰器进行装饰
def generator_code(length):   # 功能函数
    code = ''
    ss = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMzxcvbnmasdfghjklpoiuytrewq'
    for i in range(length):
        ran = random.choice(ss)
        code += ran
        pass
    print("本次的验证码为:", code)
    pass

其他知识

1. 引用计数

方法 sys.getrefcount(a),需要 import sys

对a进行引用计数,真实值为返回结果-1,原因是在使用该方法时传入a,也会让a的引用计数+1

2. 开放封闭原则

开放:对于拓展是开放的

任何一个程序,不可能在设计之初就确定好所有的功能,并且在未来漫长的应用和维护过程中不许要做出任何的更新和修改。因此开发者必须允许代码拓展,添加新的功能。

封闭:对于修改是封闭的

我们写的函数可能已经在各种地方被各种人所实用,如果我们此时对其进行修改,可能会影响正在使用该函数的用户。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值