装饰器
前言
函数名的多种用法
# 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函数
闭包函数
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
装饰器概念
装饰器模板
# 这就是一个装饰器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
装饰器推导过程
装饰器语法糖
语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会
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