今日内容总结
global与nonlocal
1.global 可以在局部修改全局名称空间的数据
代码实现:
naem = 'xiaochen'
def fff ():
global name
name = 'chen'
fff()
print(name) # chen 直接从局部修改全局名称空间
2.nonlocal 在局部嵌套的结构中可以在所处局部名称空间去修改上一级局部空间的数据
代码实现:
def fff():
name = 'xiaochen'
def aaa ():
nonlocal name
name = 'chen'
aaa()
print(name) # 正常输出的结过应该时'xiaochen'
fff()

函数名的多种用法
函数名所绑定的其实就是一个内存地址 不同于变量名 内存地址存储的是一段代码而不是数据值
1.可以当作变量名赋值
def fff():
pass
res = fff # 加括号则会执行代码 此时res所接收的是函数体代码的返回值
2.可以当作函数的参数
def fff():
pass
def aaa(a):
print(a)
aaa(fff) # 所获得的是fff函数的内存地址
3.可以作为函数的返回值
def fff():
pass
def aaa():
return fff
res = aaa() # 所获得的是fff函数的内存地址
'''可以在res后面再追加一个括号 res()就等价与fff() 可以执行函数fff的函数体代码'''
4.可以是一个容器类型(存放多种数据的数据类型)的数据
使用该类文本可以升级编码的编写 不用反复的编写 if elif 的结构 实现代码分区快也方便纠错
eg:

闭包函数
'''
定义再函数内部的函数 并且使用到了外部函数的名称空间的名字
1.函数内部
2.使用外部名称空间的名字
'''
def fff():
name = 'xiaochen'
def aaa():
print(name) # xiaochen
aaa()
fff()
闭包函数的实际运用:可以作为给函数体代码传参的一种方式
'''给函数体代码传参的两种方式'''
# 方式一 缺什么传什么
def fff(name,age):
print(f'姓名:{name},年龄:{age}')
fff('xiaochen',19) # 在括号里填写即可
# 方式二 使用闭包函数传
def fff(name,age):
def aaa():
print(f'姓名:{naem},年龄:{age}')
return aaa
res = fff('xiaochen',19) # 填写数据值
res() # 可以直接调用上面的数据

装饰器简介
1.概念:在不改变函数源代码与调用方式的情况下给装饰代码添加功能
2.本质:
将函数参数,名称空间,函数名的多种用法加上闭包函数综合在一起
3.口诀:
对修改封闭 对扩张开放
4.储备知识:
# 时间相关操作
print(time.time()) # 时间戳(距离1970-01-01的时间 单位是秒)
time.sleep(输入时间)
# 括号内输入的时间为休息时间 在下面的代码需要等待休息时间结束才可以运行
print ('hello')
装饰器的推导流程
# ****************************十分重要************************************
import time
def index():
time.sleep(1)
print('from index')
def home():
time.sleep(1)
print('form home')
stear_time = time.time()
index()
end_time = time.time()
print('index所需要的时间:',end_time-stear_time)

1.当index需要被反复调用 不可使用c+v 那么就使用函数
def get_time():
stear_time = time.time()
time.sleep(1)
end_time = time.time()
print('get_time执行的时间:',end_time-stear_time)
get_time()

2.上述代码只能执行get_time 因为被写死了 所以可以添加参数让代码兼容性变强
def get_time(xxx):
stear_time = time.time()
xxx()
end_time = time.time()
print(f'{xxx}所执行的时间:',end_time-stear_time)
get_time(index)
get_time(home)
# 在括号内输入即可获取

3.虽然提升了代码的兼容性 但是还是没有满足装饰器的要求(不改变提取方式) 试着用闭包函数
def outer(xxx):
def get_time():
stear_time = time.time()
xxx()
end_time = time.time()
print(f'{xxx}函数所执行的时间:',end_time-stear_time)
return get_time
res = outer(index)
res()
res1 = outer(home)
res1()
# 做到使用res()来调用

4.在上述的方法中使用res()来调用 还是不满足要求 还可以优化 # 关键的一步
def outer(xxx):
def get_time():
stear_time = time.time()
xxx()
end_time = time.time()
print(f'{xxx}函数执行所需的时间:',end_time-stear_time)
return get_time
index = outer(index)
index()
home = outer(home)
home()
# 看上去满足了要求

5.上述的代码以及满足了装饰器的要求 但只能是无参函数 所以兼容性还是低了
def func():
time.sleep()
def func1(x,x):
time.sleap(1)
def outer(xxx):
def get_time():
stear_time = time.time()
xxx()
end_time = time.time()
print(f'{xxx}函数执行所用的时间:',end_time-stear_time)
return get_time
func = outer(func)
func()
func1 = puter(func1)
func1(1,2)
# 如果是func1的情况 会出现报错

6.利用可变长参数 再次提升代码的兼容性
def func(a):
time.sleep(1)
def func1(a,b):
time.sleep(1)
def outer(xxx):
def get_time(*a,**k):
stear_time = time.time()
xxx(*a,**k)
end_time = time.time()
print(f'{xxx}函数执行所需的时间:',end_time-stear_time)
return get_time
func = outer(func)
func(1)
func1 = outer(func1)
func1(1,2)
# 当不知道有多少参数 或者有没有参数时可以用

7.如果被装饰的函数有返回值
def func():
return 'func'
def func1():
return 'func1'
def outer(xxx):
def fff(*a,**k):
xxx(*a,**k)
return res
return fff
func = outer(func)
rus = func()
print(rus)
func1 = outer(func1)
rus = func1()
print(rus)

装饰器模板
def outer(xxx):
def inner(*a,**k):
print('被装饰前的操作')
res = xxx(*a,**k)
print('被装饰后的操作')
return res
return inner
# 在不理解流程推导可以直接套用模板
装饰器语法糖
def outer(xxx):
def inner(*a,**k):
print('被装饰前的操作')
rex = xxx(*a,**k)
print('被装饰后的操作')
return rex
return inner
'''语法糖可将下面紧挨着的函数名当作第一个参数自动传给@后面的函数名调用'''
@outer # 此步骤就等于 func=outer(func)
def func:
return func
func()
#使用@的时候 下面要紧挨着 别空开
