今日内容概要
- global与nonlocal
- 函数名的多种用法
- 闭包函数
- 装饰器简介
- 装饰器推导流程
- 装饰器模板
- 装饰器语法糖
今日内容详细
global与nonlocal
'''通过global声明 可以通过局部名称空间直接修改全局名称空间中的数据'''
a = 100
def func():
global a
a = 888
func()
print(a) # 不用global声明则打印全局名称空间中a的数据值 声明后运行函数会将新数据值赋予到全局名称空间中
'''通过nonlocal声明 可以通过内层局部名称空间修改外层局部名称空间中的数据值'''
def func1():
b = 11
def func2():
nonlocal b
b = 22
func2()
print(b) # 22
func1()
函数名的多种用法
函数名其实绑定的也是一块内存地址,只不过该内存地址里面存放的不是数据值而是一段代码,函数名加括号就会找到该代码并执行
当做变量名赋值
def func():pass
res = func
res() # 将函数名绑定的内存地址再绑定给res 这样res()也能够运行原本的函数
当做函数的参数
def func():
print('from func')
def func1(a):
print('from func1')
a()
func1(func)
当做函数的返回值
def func():
print('from func')
def func1():
print('from func1')
return func
res = func1()
res()
# 嵌套使用
def index():
print('from index')
def func():
print('from func')
return func
res = index()
print(res)
res()
可以当做容器类型(可以存放多个数据的数据类型)的数据
def register():
print('注册功能')
def login():
print('登录功能')
def my_remove():
print('删除功能')
def show():
print('查看功能')
'''定义功能编号与功能的对应关系'''
func_dict = {
'1': register,
'2': login,
'3': my_remove,
'4': show
}
while True():
print('''
1.注册功能
2.登录功能
3.删除功能
4.查看功能
''')
choice = input('请输入对应编号:')
if choise in func_dict:
func = func_dict.get(choice) # 字典通过k取对应的value值
func() # 运行取到对应函数名的代码
else:
print('功能编号不存在')
'''用原本的方法需要一个一个写判断,当判断条件比较多时很麻烦'''
if choice == '1':
register()
elif choice == '2':
login()
elif choice == '3':
my_remove()
elif choice == '4':
show()
else:
print('真多啊')
闭包函数
'''
定义在函数内部的函数 并且用到了外部函数名称空间中的名字
1.定义在函数内部的函数
2.用到外部函数名称空间中的名字
'''
# 实例
def outer():
age = 18
def inner():
print(age)
# 内部函数中调用了外部函数中的变量age
闭包函数实际应用>>>>是另外一种给函数体代码传参的方式
'''给函数体代码传参'''
方式1:代码里面缺什么变量名形参中就补什么变量名
def register(name, age):
print(f'''
姓名:{name}
年龄:{age}
''')
register('jack', 18)
方式2:闭包函数
def outer(name, age):
def register():
print(f'''
姓名:{name}
年龄:{age}
''')
return register
res = outer('jason', 18)
res()
res() # 多次调用的时候不用重复传值
装饰器
装饰器简介
1.概念
在不改变被装饰对象源代码和调用方式的情况下给被装饰对象添加新的功能
2.本质
并不是一门新的技术,而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3.口诀
对修改封闭 对扩展开放
4.储备知识
时间相关操作
import time # 导入time模块
print(time.time()) # 时间戳(距离1970-01-01 00:00:00所经历的秒数)
time.sleep(3) # 代码运行到这停留三秒,括号内可以是任意数字
'''小案例'''
count = 0
while count < 100:
start = time.time() # 记录开始时间戳
print('运行中')
count += 1
end_time = time.time() # 记录结束时间戳
print('运行消耗的时间:', end_time - start)
装饰器推导流程
'''定义函数,想要获取它运行的时长'''
import time
def func():
time.sleep(3)
print('from func')
'''1.直接在调用func函数的前后添加代码'''
start = time.time()
func()
end_time = time.time
print('函数func执行的时长为:', end_time - start)
'''2.当func函数调用的地方较多 代码不可能反复拷贝>>>相同的代码需要在不同的位置反复执行>>>再定义成函数'''
def get_time():
start = time.time()
func()
end_time = time.time
print('函数func执行的时长为:', end_time - start)
'''3.函数体代码写死了 只能统计func的执行时间 所以需要传参变化统计的函数'''
def get_time(a):
start = time.time()
a()
end_time = time.time
print('函数func执行的时长为:', end_time - start)
get_time(func)
'''4.虽然实现了一定的兼容性 但是并不符合装饰器的特征 第一种传参不写 只能考虑闭包'''
def outer(a):
def get_time():
start = time.time()
func()
end_time = time.time
print('函数func执行的时长为:', end_time - start)
return get_time
res = outer(func) # res是一个变量名 可以任意命名
res()
'''5.调用方式还是不对 如何变形>>>变量名赋值绑定'''
def outer(a):
def get_time():
start = time.time()
func()
end_time = time.time
print('函数func执行的时长为:', end_time - start)
return get_time
func = outer(func)
# 括号内func是原本的函数名 左边的func其实就是get_time只是命名的原来的函数相同
func()
'''6.上述装饰器只能装饰无参函数 兼容性太差'''
def func1(a):
time.sleep(0.1)
print('from func1')
def func2(a, b):
time.sleep(0.2)
print('from func2')
def outer(a):
def get_time(a):
start = time.time()
func()
end_time = time.time
print('函数func执行的时长为:', end_time - start)
return get_time
fucn1 = outer(fucn1)
func1(1)
func2 = outer(func2)
func2(1, 2) # 会报错 传的参数个数不对
'''7.被装饰的函数不知道有没有参数以及有几个参数 如何兼容'''
def func1(a):
time.sleep(0.1)
print('from func1')
def func2(a, b):
time.sleep(0.2)
print('from func2')
def outer(a):
def get_time(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end_time = time.time
print('函数func执行的时长为:', end_time - start)
return get_time
fucn1 = outer(fucn1)
func1(1)
func2 = outer(func2)
func2(1, 2) # 这样不管传几个参数或者不传都不会报错
'''8.如果被装饰的函数有返回值'''
def func1(a):
time.sleep(0.1)
print('from func1')
return 'func1'
def func2(a, b):
time.sleep(0.2)
print('from func2')
def outer(a):
def get_time(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end_time = time.time
print('函数func执行的时长为:', end_time - start)
return get_time
func1 = outer(func1)
res = func1(123) # 将获取到的返回值定义给res
print(res) # func1
装饰器模板
'''非常重要 要牢记'''
def outer(func):
def inner(*args, **kwargs):
# 执行被装饰对象之前可以做的额外操作
res = func()
# 执行被装饰对象之后可以做的额外操作
return res
return inner
装饰器语法糖
@装饰器 就是语法糖
'''语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数调用'''
def outer(func):
def inner(*args, **kwargs):
print('执行被装饰对象之前可以做的额外操作')
res = func()
print('执行被装饰对象之后可以做的额外操作')
return res
return inner
@outer # func = outer(func) 相当于自动执行这行代码
def func():
print('from func')
return 'func'
func()
作业
'''编写一个用户认证装饰器
函数:register login transfer withdraw
基本要求
执行每个函数的时候必须先校验身份 eg: jason 123
拔高练习(有点难度)
执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
提示:全局变量 记录当前用户是否认证'''
a = True
def outer(func):
def inner(*args, **kwargs):
global a
if a:
name = input('username:')
pwd = input('password:')
if name == 'jason' and pwd == '123':
a = False
res = func(*args, **kwargs)
return res
else:
print('用户名或密码错误')
else:
res = func(*args, **kwargs)
return res
return inner
@outer
def register():
print('from register')
@outer
def login():
print('from login')
@outer
def transfer():
print('from transfer')
@outer
def withdraw():
print('from withdraw')
register()
login()
transfer()
withdraw()
标签:12,函数,Python,res,基础,func,time,print,def
From: https://www.cnblogs.com/lzjjjj/p/16781170.html