闭包函数与装饰器
目录一、global与nonlocal
1.global:局部名称空间直接修改全局名称空间中的数据,声明局部名称空间中的变量名操作的是全局名称空间的变量名
eg:
x = 99
def func():
global x # 声明局部变量中的x操作的是全局名称的x
x = 22 # 将原绑定关系解开,重新绑定22
print(x)
func()
# 可变数据类型不需要关键字声明
eg:
l1 = [1,2,3,4]
def func():
l1 = [1,2,3]
l1.append(999)
print(l1)
func() # [1, 2, 3, 999]
2.nonlocal:内层局部名称空间修改外层局部名称中的数据
eg:
def func():
x =11
def func1():
nonlocal x
x =22
func1()
print(x) # 22
func()
# 可变数据类型不需要关键字声明
eg:
def func():
l1 = [1,2,3,4]
def func1():
l1.append(888)
func1()
print(l1) # [1, 2, 3, 4, 888]
func()
二、函数名的多种用法
函数名绑定的也是一块内存地址,只不过地址里面放的不是数据值而是一段代码,函数名加括号就能找到该代码并且执行
1.可以当做变量名赋值
eg :
def index():
pass
res = index()
res()
# res也绑定index绑定的数据值
2.可以当做函数的参数
eg:
def index():
print('from')
def func(a):
print(a)
a()
func(index) # a形参与index实参形成动态绑定
3.可以当做函数的返回值
eg:
def index():
print('from')
def func():
print('to')
return index
res = func()
print(res) # <function index at 0x000001EAC74961F0>
res()
eg:
def index():
print('from')
def func():
print('to')
return func
res = index()
print(res)
res()
4.可以当容器类型(可以存放多个数据的数据类型)的数据
eg:
def register():
print('注册')
def login():
print('登录')
def transfer():
print('转账')
def withdraw():
print('提现')
def shopping():
print('购物')
func_dict = {
'1':register,
'2':login,
'3':transfer,
'4':withdraw,
'5':shopping
}
while True:
print('''
1.注册
2.登录
3.转账
4.提现
5.购物
''')
choice = input('请输入您的选择').strip()
if choice in func_dict:
func_dict.get(choice)() # 通过键拿值
else:
print('功能编号不存在')
三、闭包函数
定义在函数内部的函数,并且用到了外部函数名称空间中的名字
条件:
1.定义在函数内部
2.用到外部函数名称空间中的名字
简单的一个闭包函数案例:
def index():
name = 'jia'
def inner():
print(name)
闭包函数实际应用>>>:是一种给函数体代码传参的方式!!!
1.形参方式:代码里面缺什么变量名形参里面就补什么变量名
eg:
def register(name,age): # 缺什么变量名补什么变量名
print(f'''
name:{name}
age:{age}
''')
register('jason',18)
2.闭包方式
eg:
def outer(name,age):
def register():
print(f'''
name:{name}
age:{age}
''')
return register
res = outer('jason',19)
res()
# name:jason age:19
四、装饰器简介
1.概念:
在不改变被装饰对象原代码和调用方式的情况下,给被装饰对象添加新的功能
2.本质:
并不是一门新的技术,而是由函数参数,名称空间,函数的多种用法,闭包函数组合到一起的结果
3.原则:
对修改封闭,对拓展开放
(不可以修改,但是可以添加新功能)
4.时间戳:
import time
print(time.time()) # 1665479593.2389407
# 时间戳,1970-01-01 00:00:00所经历的秒数
eg:
import time
count = 0
start_time = time.time()
while count < 10:
print('你猜猜')
count += 1
end_time = time.time()
print('循环消耗的时间:',end_time - start_time)
五、装饰器推导流程
推导流程:
import time
def index():
time.sleep(0.5)
print('from index')
def home():
time.sleep(0.6)
print('from home')
'''统计index函数执行的时间'''
start_time = time.time()
index()
end_time = time.time()
print('消耗的时间是:',end_time - start_time)
# index调用的地方较多,代码不可能反复拷贝,我们可以写一个函数然后相同代码可以在不同位置反复执行
def get_time():
start_time = time.time()
index()
end_time = time.time()
print('消耗的时间是:', end_time - start_time)
get_time(index) # 在函数名调用的时候,变换函数的参数,就能统计更多的函数的运行时间
# 以上的方法虽然好,但是不符合装饰器的特征,下面的是变量名赋值绑定,适用于装饰无参函数
def outer(xxx):
def get_time():
start_time = time.time()
xxx() # 闭包函数
end_time = time.time()
print('消耗的时间是:',end_time - start_time)
return get_time()
res = outer(index)
index()
res = outer(home)
home()
# 为了解决兼容性差,被装饰的函数不知道有没有参数及有几个参数的问题,做出如下整改
def func(a):
time.sleep(0.5)
print('from func', a)
def func1(a,b):
time(0.6)
print('from func1', a,b)
def func2(a,b,c):
time.sleep(0.4)
print('from func2', a,b,c)
def outer(xxx):
def get_time(*args,**kwargs):
start_time = time.time()
xxx(*args,**kwargs)
end_time = time.time()
print('函数消耗的时间:',end_time - start_time)
get_time()
func = outer(111)
func()
func1 = outer(11,22)
func1()
func2 = outer(11,22,33)
func2()
# 最后完整版,被装饰的函数有返回值
def func(a):
time.sleep(0.1)
print('from func', a)
return func
def func1(a,b):
time(0.6)
print('from func1', a, b)
return func1()
def outer(xxx):
def get_time(*args,**kwargs):
start_time = time.time()
res = xxx(*args, **kwargs)
end_time = time.time()
print('函数消耗的时间:', end_time - start_time)
return res
return get_time
func = outer(func)
res = func(123)
print(res)
六、装饰器模板
def outer(func):
def inner(*args,**kwargs):
#执行被操作对象之前的操作
res = func(*args,**kwargs)
# 执行被操作对象之前的操作
return res
return inner()
七、装饰器语法糖
def outer(func):
def inner(*args,**kwargs):
#执行被操作对象之前的操作
res = func(*args,**kwargs)
# 执行被操作对象之前的操作
return res
return inner()
# 语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数调用
模板:
def outer(func):
def inner(*args,**kwargs):
#执行被操作对象之前的操作
res = func(*args,**kwargs)
# 执行被操作对象之前的操作
return res
return inner()
@outer # func = outer(func)
def func():
print('哈哈哈')
return func
@outer # index = outer(index)
def index():
print('hhhh')
return index
func()
index()
八、作业
data_dict = {}
def register():
# print('注册')
while True:
username = input('请输入注册的用户名').strip()
if username in data_dict:
print('用户名已存在')
continue
username = input('请输入您的用户名').strip()
password = input('请输入您得密码').strip()
money = input('请输入您的金额').strip()
temp_dict = {}
temp_dict['username'] = username
temp_dict['password'] = password
temp_dict['money'] = money
data_dict[username] = temp_dict
print(f'员工{username}注册成功')
break
def login():
# print('登录')
while True:
username = input('请输入注册的用户名').strip()
if username not in data_dict:
print('用户未注册,不能登录')
continue
password = input('请输入您的密码').strip()
emp_data = data_dict.get(username)
emp_name = emp_data['username']
emp_pwd = emp_data['password']
if emp_name == username and emp_pwd == password:
print('登录成功')
break
else:
print('用户名或者密码有误')
break
def transfer():
while True:
dict_user = {'jia':123,'jason':321}
money = 888
emp_money = eval(input('请输入您要转账的金额'))
if emp_money <= money:
user = input('请输入您要转账的账户')
if user in dict_user.keys():
y_money = money - emp_money
print('转账成功,您的余额为',y_money)
break
def withdraw():
while True:
money = 888
emp_money = eval(input('请输入您要提现的金额'))
if emp_money <= money:
y_money = money - emp_money
print('提现成功,您的余额为',y_money)
break
func_dict = {
'1':register,
'2':login,
'3':transfer,
'4':withdraw
}
while True:
print('''
1.注册
2.登录
3.转账
4.提现
''')
choice = input('请输入您要操作的功能编号').strip()
if choice in func_dict:
func_name = func_dict.get(choice)
func_name()
else:
print('没有你要操作的功能编号')
标签:闭包,index,函数,res,func,time,print,装饰,def
From: https://www.cnblogs.com/zx0524/p/16782895.html