目录
函数高级带上期总结补充
今日概要
- global与nonlocal
- 函数名的多种用法
- 闭包函数
- 装饰器简介
- 无参装饰器
- 有参装饰器
- 装饰器模板
- 装饰器语法糖
今日内容详细
global与nonlocal
money = 6666
def index():
global money
money = 123
index()
print(money)
"""局部名称空间直接修改全局名称空间中的数据"""
def index1():
name = 'jason'
def inner():
nonlocal name
name = 'kevin'
inner()
print(name)
index1()
"""内层局部名称空间修改外层局部名称空间中的数据"""
函数名的多种用法
函数名其实绑定的也是一块内存地址 只不过该地址里面存放的不是数据值而是一段代码 函数名加括号就会找到该代码并执行
1.可以当做变量名赋值
def index(): pass
res = index
print(res)
2.可以当做函数的参数
def index1():
print('from index1')
def func(a):
print(a)
a()
func(index1)
3.可以当函数的返回值
def index():
print('from index')
def func():
print('from func')
return index
res = func()
print(res)
res()
4.可以当做容器类型(可以存放多个数据的数据类型)的数据
# 各种功能的简写
def register():
print('注册功能')
def login():
print('登录功能')
def withdraw():
print('提现功能')
def transfer():
print('转账功能')
def shopping():
print('购物功能')
# 定义功能编号与功能的对应关系
func_dict = {
'1':register,
'2':login,
'3':withdraw,
'4':transfer,
'5':shopping
}
while True:
print("""
1.注册功能
2.登录功能
3.提现功能
4.转账功能
5.购物功能
""")
# 使用这种方法即便有100种功能也只需要这几行代码
choice = input('请输入你选择的功能编号:').strip()
if choice in func_dict:
func_name = func_dict.get(choice)
func_name()
else:
print('功能未开发')
# if choice == '1':
# register()
# elif choice == '2':
# login()
# elif choice == '3':
# withdraw()
# elif choice == '4':
# transfer()
# elif choice == '5':
# shopping()
# else:
# print('未开发功能')
闭包函数
"""
定义函数内部的函数 并且用到了外部函数名称空间中的名字
1.定义在函数内部
2.用到外部函数名称空间中的名字
"""
def index():
name = 'jason'
def inner():
print(name)
inner()
index()
闭包函数实际应用>>>:是另一种给函数体代码传参的方式!!!
# 给函数体代码传参的方式1:代码里面缺什么变量名形参里面就补什么变量名
def register(name, age):
print(f"""
姓名:{name}
年龄:{age}
""")
register('jason', 18)
# 给函数体代码传参的方式2:闭包函数
def outer(name, age):
def register():
print(f"""
姓名:{name}
年龄:{age}
""")
return register
res = outer('jaosn', 18)
res()
res()
res = outer('kevin', 28)
res()
装饰器简介
1.概念
在不改变被装饰对线原代码和调用方式的情况下给被装饰对象添加新的功能
2.本质
并不是一种新的技术 而是由函数参数,名称空间,函数名多种用法,闭包函数组合到一起的结果
3.口诀
对修改封闭 对扩展开放
4.储备知识
知识相关操作
import time
print(time.time()) # 时间戳(距离1970-01-01 00:00:00所经历的秒数)
time.sleep(3)
print('睡醒了 干饭')
count = 0
# 循环回去先获取时间戳
start_time = time.time()
while count < 1000:
print('哈哈哈')
count += 1
end_time = time.time()
print('循环消耗的时间:', end_time - start_time)
装饰器推导流程
import time
def index():
time.sleep(2)
print('from index')
def home():
time.sleep(1)
print('from home')
'''1.直接在调用index函数的前后添加代码'''
start_time = time.time()
index()
end_time = time.time()
print('函数index的执行时间为>>>:', end_time - start_time)
'''2.index调用的地方较多 代码不可能反复拷贝>>>:相同的代码需要在不同的位置反复执行>>>:函数'''
def get_time():
start_time = time.time()
index()
end_time = time.time()
print('函数index的执行时间为>>>:', end_time - start_time)
get_time()
'''3.函数体代码写死了 只能统计index的执行时间 如何才能做到统计更多的函数运行时间 直接传参变化统计的函数'''
def get_time(xxx):
start_time = time.time()
xxx()
end_time = time.time()
print('函数index的执行时间为>>>:', end_time - start_time)
get_time(index)
get_time(home)
'''4.虽然实现了一定的兼容性 但是并不符合装饰器的特征 第一种传参不写 只能考虑闭包'''
def outer(xxx):
def get_time():
start_time = time.time()
xxx()
end_time = time.time()
print('函数index的执行时间为>>>:', end_time - start_time)
return get_time
res = outer(index)
res()
res1 = outer(home)
res1()
'''5.调用方式还是不对 如何变形>>>:变量名赋值绑定(******)'''
def outer(xxx):
def get_time():
start_time = time.time()
xxx()
end_time = time.time()
print('函数index的执行时间为>>>:', end_time - start_time)
return get_time
index = outer(index)
index()
home = outer(home)
home()
'''6.上述装饰器只能装饰无参函数 兼容性太差'''
def func(a):
time.sleep(0.1)
print('from func', a)
def func1(a, b):
time.sleep(0.2)
print('from func1', a, b)
def func2():
time.sleep(0.3)
print('from func3')
func(123)
def outer(xxx):
def get_time(a, b):
start_time = time.time()
xxx()
end_time = time.time()
print('函数index的执行时间为>>>:', end_time - start_time)
return get_time
# 必须要没参数传值
func2 = outer(func2)
func2()
# 必须要有一个参数传值
func = outer(func)
func(1)
# 必须要有两个参数传值
func1 = outer(func1)
func1(1, 2)
'''7.被装饰的函数不知道有没有参数以及有几个参数 如何兼容'''
def func(a):
time.sleep(0.1)
print('from func', a)
def func1(a, b):
time.sleep(0.2)
print('from func1', a, b)
def outer(xxx):
def get_time(*args, **kwargs):
start_time = time.time()
xxx(*args, **kwargs)
end_time = time.time()
print('函数index的执行时间为>>>:', end_time - start_time)
return get_time
func = outer(func)
func(123)
func1 = outer(func1)
func1(1, 2)
'''8.如果被装饰的函数有返回值'''
def func(a):
time.sleep(0.1)
print('from func', a)
return 'func'
def func1(a, b):
time.sleep(0.2)
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('函数index的执行时间为>>>:', end_time - start_time)
return res
return get_time
func = outer(func)
func(123)
func1 = outer(func1)
res = func1(123, 222)
print(res)
装饰器模板
# 务必掌握
def outer(func):
def inner(*args, **kwargs):
# 执行被装饰对象之前可以做的额外操作
res = func(*args, **kwargs)
# 执行被装饰对象之后可以做的额外操作
return res
return inner
装饰器语法糖
def outer(func_name):
def inner(*args, **kwargs):
# 执行被装饰对象之前可以做的额外操作
res = func_name(*args, **kwargs)
# 执行被装饰对象之后可以做的额外操作
return res
return inner
"""
语法糖会自动挡将下面紧挨着的函数名当做第一个参数自动传给@函数调用
"""
@outer # func = outer(func)
def func():
print('from func')
return 'func'
@outer # index = outer(index)
def index():
print('from index')
return 'index'
res = func()
print(res)
res1 = index()
print(res1)
函数高级总结补充
-
昨日作业详解
-
多层语法糖问题
-
有参装饰器
-
装饰器修复技术
-
递归函数
今日内容详细
昨日作业详解
is_login = False
def outer(func_name):
def inner(*args, **kwargs):
global is_login
if is_login:
res = func_name(*args, **kwargs)
return res
username = input('请输入用户名:').strip()
userpwd = input('请输入密码:').strip()
if username == 'jason' and userpwd == '123':
is_login = True
res = func_name(*args, **kwargs)
return res
else:
print('用户名或密码错误无法执行函数')
return inner
@outer
def register():
print('注册功能')
@outer
def login():
print('登录功能')
@outer
def shopping():
print('购物功能')
register()
login()
shopping()
多层语法糖
def outer1(func1):
print('加载了outer1')
def wrapper1(*args, **kwargs):
print('执行了wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outer2(func2):
print('加载了outer2')
def wrapper2(*args, **kwargs):
print('执行了wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outer3(func3):
print('加载了outer3')
def wrapper3(*args, **kwargs):
print('执行了wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outer1
@outer2
@outer3
def index():
print('from index')
index()
"""
多层语法糖 加载顺序由下往上
每次执行之后如果上面还有语法糖 则直接将返回值函数名传给上面的语法糖
如果上面没有语法糖了 则变形index = outer1(wrapper2)
"""
有参装饰器
# 校验用户是否登录装饰器
def outer_plus(mode):
def outer(func_name):
def inner(*args, **kwargs):
username = input('请输入用户名:').strip()
userpwd = input('请输入密码:').strip()
if mode == '1':
print('数据直接写死')
elif mode == '2':
print('数据来源于文本文件')
elif mode == '3':
print('数据来源于字典')
elif mode == '4':
print('数据来源于数据库')
res = func_name(*args, **kwargs)
return res
return inner
return outer
'''当装饰器中需要额外的参数时>>>:有参装饰器'''
"""
函数名加括号执行优先级最高 有参装饰器的情况
先看函数名加括号的执行
然后再是语法糖的操作
"""
@outer_plus
def index():
print('from index')
index(1)
@outer_plus
def func():
print('from func')
func(2)
装饰器模板
# 最常用的无参装饰器
def outer(func_name):
def inner(*args, **kwargs):
print('被装饰对象执行前能执行的操作')
res = func_name(*args, **kwargs)
print('被装饰对象执行后能执行的操作')
return res
return inner
@outer
def index():
pass
# 不常用的有参装饰器
def outer_plus(a):
def outer(func_name):
def inner(*args, **kwargs):
print('被装饰对象执行前能执行的操作')
res = func_name(*args, **kwargs)
print('被装饰对象执行后能执行的操作')
return res
return inner
return outer
@outer_plus('MySQL')
def func():
pass
装饰器修复技术
from functools import wraps
def outer(func_name):
@wraps(func_name) # 仅仅是为了让装饰器的效果更加逼真 平时可以不写
def inner(*args, **kwargs):
"""我是inner 我擅长让人懵逼"""
res = func_name(*args, **kwargs)
return res
return inner
@outer
def func():
'''我是真正的func 我很强大 我很牛 我很聪明'''
pass
help(func)
print(func)
func()
递归函数
1.函数的递归调用
函数直接或间接的调用了函数自身
# # 直接调用
# def index():
# print('from index')
# index()
# index()
# # 间接
# def index():
# print('from index')
# func()
#
# def func():
# print('from func')
# index()
#
# func()
'''最大递归深度:python解释器添加的安全措施'''
count = 0
def index():
global count
count += 1
print(count)
index()
index()
'''官网提供的最大递归深度为1000 我们在测试的时候可能会出现996 997 998'''
2.递归函数
1.直接或间接调用自己
2.每次调用都必须比上一次简单 并且需要有一个明确的结束条件
递推:一层层的往下
回溯:基于明确的结果一层层往上
"""
get_age(5) = get_age(4) + 2
get_age(4) = get_age(3) + 2
get_age(3) = get_age(2) + 2
get_age(2) = get_age(1) + 2
get_age = 18
"""
def get_age(n):
if n == 1:
return 18
return get_age(n - 1) + 2
res = get_age(5)
print(res)
作业
1.利用递归函数依次打印列表中每一个数据值
l1 = [1, [2, [3, [4, [5, [6, [7, [8, ]]]]]]]]
def func(a):
for i in a:
if type(i) == list:
func(i)
else:
print(i)
func(l1)