装饰器

前言

image

函数名的多种用法

image

# 1.函数名是名字
def index():
    pass
print(index)  # <function index at 0x000002EDA843E040>  # 函数名也是个名字 指向内存中的函数
index = 1
print(index)  # 1  # index这个名字现在指向 1 啦!
# 2.函数名可以当做函数的参数
def index():
    print('from index')
def func(a):  #  a=index 临时绑定
    a() # 执行index
func(index)  # from index
# 3.函数名可以作为函数的返回值
def index():
    print('from index')

def func():
    print('from func')
    return index  # 会去全局名称空间找index这个名字

res = func()  # res现在是index
print(res)
res()  # 相当于调用index函数
# 4.函数名可以当做容器类型的数据
def index():
    print('from index')

list1 = [1, 2, 3, 4, 'miku', index]  # 函数名也放里面了
list1[-1]()  # 用索引取出 然后调用index函数

闭包函数

image

def outer(name):
    def inner():  # inner是在函数内部的函数
        print(name)  # 内层函数用到了外部函数名称空间的名字name
    return inner

back = outer('miku')  # 传入miku name和miku绑定  # back是outer的返回值inner函数
back()  # 调用内部的inner函数 inner函数去外层找name 找到了miku 输出miku

back2 = outer('alice') 
back2() # alice

补充time模块 时间戳

# 1.基本使用
import time  # 意思是导入time这个模块
time.sleep(1)  # 意思是程序到这里停止1秒
# 2.时间戳
start_time = time.time()  # 获取当前时间戳
print(start_time)  # 1665415648.5771186  # 现在时间距离 1970年1月1日 的 秒数
time.sleep(2)
stop_time = time.time() # 再获取一次当前时间戳
print(stop_time - start_time)  # 2.0005736351013184

装饰器概念

image

装饰器模板

# 这就是一个装饰器outer 其实就是一个函数
def outer(func):
    def inner(*args, **kwargs):
        # 执行被装饰对象之前可以做的额外操作
        res = func(*args, **kwargs)
        # 执行被装饰对象之后可以做的额外操作
        return res
    return inner

使用装饰器模板

def outer(func_name):  # 装饰器
    def inner(*args, **kwargs):
        print('函数之前')
        res = func_name(*args, **kwargs)
        print('函数之后')
        return res

    return inner


def world(a):  # 被装饰函数
    print(a)
    return 'miku'


world = outer(world)  # inner狸猫换太子 这个world实际是内层的inner
world('你好')


# back = world('hello') # 获取inner的返回值
# print(back)  # miku

装饰器推导过程

image

装饰器语法糖

语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会
image

def outer(func_name):
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner

def func():
    print('from func')
    return 'func'
func = outer(func)  # 这一段代码很容易让人感到疑惑  # 所以使用语法糖来避免程序员出错
func()
"""
语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数调用
"""
@outer  # 相当于写了 index = outer(index)
def index():
    print('from index')
    return 'index'

index()  

练习

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


def withdraw(func_name):  # 装饰器
    def inner(*args, **kwargs):
        global certification_ok  # 全局标志位
        if certification_ok == False:
            print('进行认证...')
            username = input('请输入用户名>>>:').strip()
            password = input('请输入密码>>>:').strip()
            if username == 'miku' and password == '123':
                res = func_name(*args, **kwargs)
                certification_ok = True
                return res
            else:
                print('失败')
        elif certification_ok == True:
            res = func_name(*args, **kwargs)
            return res
        else:
            print('出现什么情况了??')

    return inner


@withdraw
def register():
    print('注册功能运行了')


@withdraw
def login():
    print('登录功能运行了')


@withdraw
def transfer():
    print('转账功能运行了')


function_dict = {
    '1': register,  # 注册功能
    '2': login,  # 登录功能
    '3': transfer,  # 转账功能
}

# 执行每个函数的时候必须先校验身份 在装饰器中加一个校验身份的过程? 然后装饰每个函数??
# 执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过 全局变量
while True:
    user_choice = input('''
        ————————————————————
        '1':  注册功能
        '2':  登录功能
        '3':  转账功能
        ————————————————————-
        请输入>>>:''').strip()
    if user_choice in function_dict:
        function_dict.get(user_choice)()
    else:
        pass

posted @ 2022-10-11 16:04  passion2021  阅读(53)  评论(0编辑  收藏  举报