函数-3

目录:

  • 闭包函数

    1. 闭包函数的简介

    2. 闭包函数的实际应用

  • 装饰器

    1. 装饰器简介
    2. 装饰器的前期推导
    3. 装饰器的各种版本
    4. 装饰器的固定模板

闭包函数

  • 闭包函数的简介

    1. 定义在函数内部的函数

    2. 内部函数用了外部函数的名称空间中的名称

      只有符合这两点才能称之为闭包函数

      即 在嵌套函数中,内层函数用了外层函数的变量名

  • 闭包函数的实际应用

  1. 直接把函数体需要的参数定义成形参

    def foun(x)
         print(x)
    foun(1)    # 1
    foun(2)    # 2
    foun(3)    # 3
    
  2. 把函数体需要的参数定义成闭包函数的形式

def foun1(x):
  def foun():
   print(x)
  return foun
a = foun1(1/2/3)
a()     # 1  2  3

装饰器

  • 装饰器的简介
  1. 装饰器的本质

    在不改变被装饰对象原来的'调用方式'和'内部代码'的情况下给被装饰对象添加新的功能

  def func():
            print(123)
        func()  # 每次执行之前需要校验用户身份
  1. 装饰器的原则

    对修改封闭 对扩展开放

    能添加功能,但不能修改代码

  2. 知识储备

 import time
1.统计代码的运行时间
    # print(time.time())  # 1656987566.7260265
    '''时间戳(秒数):当前距离1970年1月1日0时0分0秒所经历的秒数'''
    # 实际应用>>>:统计代码的运行时间
    # start_time = time.time()  #  100
    # for i in range(100000):
    #     print(i)
    # end_time = time.time()
    # print('for循环的执行时间是:%s'%(end_time - start_time))
2.  让程序原地等待  
    time.sleep(3)
    '''让程序原地等待三秒'''
    print('睡醒了 还是很蒙蔽')
  • 装饰器的前期推导
import time


def index():
    time.sleep(3)
    print('from index')
'''统计index函数的执行时间'''
# start_time = time.time()  # 在调用index函数之前获取一下时间戳
# index()  # 调用index函数
# end_time = time.time()
# print(end_time - start_time)
"""
缺陷
    如果有多个index需要统计时间 则需要重复编写代码
    解决措施:
        封装成函数
"""
# def get_time():
#     start_time = time.time()  # 在调用index函数之前获取一下时间戳
#     index()  # 调用index函数
#     end_time = time.time()
#     print('函数的执行时间是:',end_time - start_time)
"""
缺陷
    如果有多个不同的函数需要统计时间 那么上述的解决措施不够完善
    解决措施: 
        给函数体添加形参(动态传参)  
"""
def home():
    time.sleep(5)
    print('from home')

def get_time(xxx):
    start_time = time.time()  # 在调用index函数之前获取一下时间戳
    xxx(*args,**kwargs)  # 调用index函数
    end_time = time.time()
    print('函数的执行时间是:',end_time - start_time)
# get_time(index)
# get_time(home)
"""
缺陷
    不同形参个数的函数无法兼容统计
    解决措施:
        *args  **kwargs
    但是在我们目前的代码中无法实现(暂且忽略)
"""
def func1(a):
    time.sleep(1)
    print('from func1')
get_time(func1)
"""
缺陷
    改变了原来的调用方式
    解决措施:
        装饰器推导流程
"""
  • 装饰器的各种版本
import time


"""针对有参无参函数如何兼容"""
def outer(xxx):
    def get_time(*args, **kwargs):
        start_time = time.time()  # 在调用index函数之前获取一下时间戳
        res = xxx(*args, **kwargs)  # 调用index函数
        end_time = time.time()
        print('函数的执行时间是:', end_time - start_time)
        return res
    return get_time

def home():
    time.sleep(2)
    print('from home')
    return '执行home函数之后的返回值'

def index(name):
    time.sleep(1)
    print('from index')
    return '执行index函数之后的返回值'

home = outer(home)
xxx = home()
print(xxx)


index = outer(index)
res = index('jason')
print(res)

# home = outer(home)
# home()

# def func(a,b,c):
#     time.sleep(1)
#     print('from func')
#
# index = outer(index)
# index('jason')
#
# home = outer(home)
# home()
#
# func = outer(func)
# func(1,2,3)

  • 装置器的固定模板
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

# import time
# def home():
#     time.sleep(1)
#     print('from home')
#     return 'home返回值'


# home = outer(home)
# res = home()
# print(res)
"""
执行home函数之前需要添加校验用户身份的功能
"""

# 装饰器语法糖
import time

@outer  #  home = outer(真正的函数名home)
def home():
    '''我是home函数 我要热死了!!!'''
    time.sleep(1)
    print('from home')
    return 'home返回值'

# help(home)
# print(home)
home()

# def index():
#     '我是index函数 我的功能很强大'
#     pass
#
# help(index)

作业

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

flag = False
def outer(approve):
    def inner(*args,**kwargs):
        global flag
        if flag:
            return approve(*args,**kwargs)
        else:
            username = input('请输入用户名:').strip()
            password = input('请输入密码:').strip()
            if username == 'jason' and password == '123':
                flag = True
                return approve(*args, **kwargs)
            else:
                print('权限不够')


    return inner


@outer
def register():
    """
    注册界面
    :return:
    """
    print('欢迎注册')



@outer
def login():
    print('正在登录')


@outer
def transfer():
    print('正在转移')

@outer
def withdraw():
    print('正在提取')

func_dic = {
    '1':register,
    '2':login,
    '3':transfer,
    '4':withdraw
}

while True:
    print("""
    1.进入注册页面
    2.进入登录页面
    3.进入转移页面
    4.进入提取页面
    """)
    # 获取用户输入的功能编号
    func_id = input('请输入功能编号:').strip()
    if func_id in func_dic:
        func = func_dic.get(func_id)
        func()
    else:
        print('没有此功能')
posted @ 2022-07-05 21:37  Nirvana*  阅读(30)  评论(0)    收藏  举报