闭包函数,装饰器

今日内容

闭包函数(重点)

  • 特征

    1.定义在函数里面的函数
    2.函数内部使用了外部函数局部空间的函数名字
    

只有同时满足这两个特征才叫做闭包函数

eg:

def outer(username):
    # username = 'jason'
    def inner():  # 嵌套在outer里面的函数
        print(username)  # 用的是outer局部空间的username

    return inner

index = outer()
index()  # jason

以上代码同时满足闭包函数的两大特征。

代码执行顺序:
在这里插入图片描述

  • 闭包函数的实际应用

eg:

def outer(username):
    # username = 'jason'

    def inner():
        print(username)

    return inner

index = outer('jason')
index()  # jason
index1 = outer('kevin')
index1()  # kevin

闭包函数是传参的另一种方式

装饰器(重点)

  • 装饰器的本质

    在不改变被装饰对象原来的调用方式内部代码的情况下给函数新增功能

      以上就是官方一点的说法,装饰器通俗易懂的说,可以类似与你买了一部手机以后,想让它外观看起来更好看一点,
      就又给它装了个手机壳。装饰器就可以类比手机壳。
    
  • 原理

对修改封闭,对扩展开放

就是,你给我加功能,我OK;但是想修改,是不能的

eg:
统计函数运行的时间

import time  # 导入时间模块
def index():
    time.sleep(3)  # 让代码在这停留3秒
    print('加油!')


start_time = time.time() # 记录运行代码前的时间戳
index()  # 调用函数
end_time = time.time()  # 记录函数运行结束的时间戳
print(end_time - start_time)  # 打印出时间戳差,就是函数运行的时间

补充知识:时间戳(当前时间距离1970年1月1日的秒数)

  • 简易版本的装饰器

思考

上述统计函数的运行时间的功能,是不是功能过于单一,但是如果写在函数体内那功能可能就更强大了

根据函数的知识,我们先将功能封装成一个函数,然后往里面传参

eg:

import time
def index():
    time.sleep(3)
    print('加油!')

def outer():  # 将功能封装为一个函数
    start_time = time.time()
    index()  # 调用函数
    end_time = time.time()
    print(end_time - start_time)

outer()  # 调用功能函数
  • 优化版本装饰器

思考:但是这样我们把函数名写死了,就只能运行这一个函数

那我们可以通过传参的形式写活

eg:

import time

def index():
    time.sleep(3)
    print('加油!')

def home():
    time.sleep(3)
    print('加油!')

def outer(func):  # 写入一个形参
    start_time = time.time()
    func()  # 传入的实参加括号就可以调用相应的函数
    end_time = time.time()
    print(end_time - start_time)


outer(index) # 传一个实参,传什么形参就是什么
outer(home)  # 传一个实参,传什么形参就是什么
输出结果:
加油!
3.000584840774536
加油!
3.0007455348968506
  • 进阶版装饰器

思考:这样的话离装饰器的定义已经很像了,但是我们可以发现调用函数的方式发生改变了,index函数是func加括号调用。

解决

通过函数体传参的形式,利用函数名的使用方式

eg:

import time

def index():
    time.sleep(3)  # 代码停3秒
    print('加油!')
    
def outer(func):  # 接收到index
    def inner():
        start_time = time.time()
        func()  # 调用正真的函数
        end_time = time.time()
        print(end_time - start_time)
    return inner


index = outer(index)  # 先看右边,传一个实参, 狸猫换太子
index()  # 这里的index其实是inner,是上面代码接收的返回值
  • 完整版本装饰器

根据之前的版本,我们还可以加入参数问题,返回值的问题,进行一个完善,最终生成了完整版本

import time

def index():
    time.sleep(3)
    print('加油!')
    
def outer(func):
    def inner(*args, **kwargs):  # 这里是狸猫换太子的index的形参
        start_time = time.time()
        res = func(*args, **kwargs)  # res接收函数的返回值,这里是正真函数的实参
        end_time = time.time()
        print(end_time - start_time)
        return res  # 然后再返回出去
    return inner

index = outer(index)
index()
  • 装饰器固定模板(记住即可)
from functools import wraps
def outer(func_name):
    @wraps(func_name)  # 仅仅是为了让装饰器不容易被别人发现 做到真正的以假乱真
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner

装饰器语法糖

  • 理解

    Python给提供了一个装饰函数更加简单的写法,那就是语法糖;
    语法糖的书写格式是: @装饰器名字,通过语法糖的方式也可以完成对已有函数的装饰。(定义装饰器)
    

也就可以把这两步省略掉

index = outer(index)

eg:

def outer(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
        return res
    return inner

@outer  # 相当于是index = outer(index)
def index():
    time.sleep(3)
    print('加油!')

今日作业

1.编写一个用户认证装饰器
基本要求
执行每个函数的时候必须先校验身份 eg: jason 123
拔高练习(有点难度)
执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
函数:register login transfer withdraw
提示:全局变量 记录当前用户是否认证

代码:

def outer(func_name):
    def inner(*args, **kwargs):
        if is_tage:  # 通过全局标志位来进行判断
            username = input('please input yours username>>>:').strip()
            password = input('please input yours password>>>:').strip()
            if {'name': username, 'pwd': password} in user_name:
                res = func_name(*args, **kwargs)  # 接收函数体运行后的返回值
                return res
            else:
                return  # 如果判断不正确,直接结束
        else:
            res = func_name(*args, **kwargs)  # 固定模式
            return res

    return inner


@outer  # 相当于join = outer(join)
def join():
    # 添加
    id = input('请输入你要添加的员工id:')
    if id in l1:
        print('员工已存在')
        return
    name = input('请输入员工姓名:')
    age = input('请输入员工年龄:')
    post = input('请输入员工的职业:')
    poy = input('请输入员工的薪资:')
    l2 = l1.fromkeys([id], {'name': name, 'age': age, 'post': post, 'poy': poy})
    l1.update(l2)
    print(f'员工{id}已经添加成功')


@outer
def change():
    # 修改
    id = input('请输入你想修改薪资员工的编号:')
    if id not in l1:
        print('员工不存在')
        return
    l1[id]['poy'] = input('请输入你想修改为多少薪资:')
    print(f'员工{id}薪资已修改成功')


@outer
def assign():
    # 指定
    id = input('请输入你要查看员工的id:')
    if id not in l1:
        print(f'{id}不存在')
        return
    print(f'''
    ----------------------info-------------------------
    id:{id}, name:{l1[id]['name']}, age:{l1[id]['age']}, post:{l1[id]['post']}, poy:{l1[id]['poy']}
    ---------------------------------------------------
    ''')


@outer
def total():
    # 全部
    for id in l1:
        print(f'''
            ----------------------info-------------------------
            id:{id}, name:{l1[id]['name']}, age:{l1[id]['age']}, post:{l1[id]['post']}, poy:{l1[id]['poy']}
            ---------------------------------------------------
            ''')


@outer
def delete():
    # 删除
    id = input('请输入你要删除员工的编号:')
    if id not in l1:
        print(f'{id}不存在')
        return
    l1.pop(id)
    print(f'员工{id}已被删除')


data = {'1': join, '2': change, '3': assign, '4': total, '5': delete}

l1 = {'001': {'name': 'jason', 'age': '25', 'post': '讲师', 'poy': '3w'},
      '002': {'name': 'kevin', 'age': '28', 'post': '运营', 'poy': '2.5w'}
      }

user_name = [
    {'name': 'lzq', 'pwd': '123'},
    {'name': 'gsy', 'pwd': '520'}
]

is_tage = True
while True:
    print('''
        1.添加员工信息
        2.修改员工薪资
        3.查看指定员工
        4.查看所有员工
        5.删除员工数据
    ''')
    choice = input('please input yours choice>>>:')
    if choice in data:
        new_data = data.get(choice)
        new_data()
        is_tage = False  # 当成功一次之后,就让其为Flase
    elif choice == '6':
        print('拜拜了你嘞!')
        break
    else:
        print('你的指令不正确!')

思考中:如何做到,认证失败,后续还可以继续认证

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值