1.global与nonlocal
"""
当我们在全局定义一个变量,在函数内可以拿到,但是无法修改(要通过global)。我们在函数内定义一个变量,在函数外无法使用
"""
1. global :局部名称空间修改全局名称空间的数据
n = 100
def index ():
global n
n = 999
index()
print (n)
2. nonlocal :内层局部名称空间修改外层局部名称空间中的数据
def index ():
n = 100
def func ():
nonlocal n
n = 500
func()
print (n)
index()
2.函数名的多种用法
函数名其实绑定的也是一块内存地址,只不过该地址里面存放的不是数据值而是一段代码,函数名加括号就会找到该代码并运行。
1. 函数名可以当作变量名赋值
def index ():
print ('from index' )
res = index
res()
2. 可以当做函数的参数
def index ():
print ('from index' )
def func (a ):
print (a)
a()
func(index)
“打印函数的函数名(不加括号)是函数的内存地址”
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 :
choice = input ('请输入您的任务编号>>>:' ).strip()
if choice in func_dict:
func_name = func_dict.get(choice)
func_name()
else :
print ('请输入正确任务编号' )
"""
函数名(不加括号)可以放在字典的值中,调用时加括号
"""
3.闭包函数
1. 定义在函数内部的函数,并且用到了外部函数名称空间的名字
"""
注意:
1.定义在函数内的函数
2.用到了外部函数名称空间中的名字
"""
def index ():
name = 'max'
def func ():
print (f'{name} 先生你好' )
func()
index()
"""
由此可以得出结论:给函数传参的方式除了实参赋值,还有闭包函数。
"""
方式1 :实参赋值
def index (name, age ):
print (f'{name} 先生今年{age} 岁了' )
index('max' , 25 )
方式2 :闭包函数
def outer (name, age ):
def register ():
print (f"""
姓名:{name}
年龄:{age}
""" )
return register
res = outer('jason' , 18 )
res()
res()
res = outer('max' , 25 )
res()
4.装饰器简介
1. 概念:在不改变被装饰对象原代码和调用方式的情况下给被装饰对象添加新的功能。
2. 本质:并不是一门新的技术,而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果。
3. 口诀:对修改封闭,对扩展开放。
4. 储备知识:事件相关操作
4.1 时间戳:从1070 年1 月1 日00 :00 到代码执行所经历的时间。
import time
print (time.time())
4.2 等待若干秒之后在执行代码:
import time
time.sleep(3 )
print ('hello world' )
4.3 统计函数执行的时间
import time
count = 1
start_time = time.time()
while count < 100 :
print ('hello world' )
count += 1
end_time = time.time()
print ('函数执行的时间:' , end_time - start_time)
5.装饰器的推导流程
1. 直接在函数调用的前后添加代码:
import time
def index ():
time.sleep(3 )
print ('from index' )
def home ():
time.sleep(1 )
print ('from home' )
start_time = time.time()
index()
end_time = time.time()
print ('函数执行的时间:' , end_time - start_time)
2. index调用的地方较多,代码不可能反复拷贝,相同的代码在不同的地方反复执行,使用函数更为便捷,定义一个get_time()函数
def get_time ():
start_time = time.time()
index()
end_time = time.time()
print ('函数执行的时间:' , end_time - start_time)
get_time()
3. 如果这么写那么函数只能统计index()函数的运行时间,如何才能做到统计更多函数运行时间?直接传参
import time
def index ():
time.sleep(3 )
print ('from index' )
def home ():
time.sleep(1 )
print ('from home' )
def get_time (xxx ):
start_time = time.time()
xxx()
end_time = time.time()
print ('函数执行的时间:' , end_time - start_time)
get_time(index)
get_time(home)
4. 上述代码调用函数只能把函数名传递到其它函数名中当做参数,改变了原函数的调用方式,因此考虑使用闭包函数:
import time
def index ():
time.sleep(3 )
print ('from index' )
def home ():
time.sleep(1 )
print ('from home' )
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)
res()
5. 上述结构函数调用时依然要被当做一个参数将函数名传递给其他函数,依然不符合调用函数的目标。
import time
def outer (xxx ):
def get_time ():
start_time = time.time()
xxx()
end_time = time.time()
print ('函数体代码执行的时间为:' , end_time - start_time)
return get_time
index = outer(index)
print (index)
index()
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(3 )
print ('from funcx' )
def outer (xxx ):
def get_time (a, b ):
start_time = time.time()
xxx(a, b)
end_time = time.time()
print ('函数体代码执行的时间为:' , end_time - start_time)
return get_time
func1 = outer(func1)
func1(1 , 2 )
7. 内层函数的参数个数要和被装饰的函数个数保持一致,被装饰得函数不知道参数个数,无法兼容
import time
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 ('函数体代码执行的时间为:' , end_time - start_time)
return get_time
func = outer(func)
func(222 )
8. 如果被装饰的函数有返回值,如何返回?
import time
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 ('函数体代码执行的时间为:' , end_time - start_time)
return res
return get_time
func1 = outer(func1)
res = func1(1 , 2 )
print (res)
6.装饰器模板
1. 模板:
def outer (func ):
def inner (*args, **kwargs ):
res = func(*args, **kwargs)
return res
return inner
2. 模板套用:
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 func2 (a, b ,c ):
time.sleep(0.2 )
print ('from func2' , a, b, c)
return 'func2'
def outer (func1 ):
def inner (*args, **kwargs ):
print ('代码执行前的操作' )
res = func1(*args, **kwargs)
print ('代码执行后的操作' )
return res
return inner
func1 = outer(func1)
res = func1(1 , 2 )
print (res)
3. 添加身份校验信息:
def func2 (a, b ,c ):
time.sleep(0.2 )
print ('from func2' , a, b, c)
return 'func2'
def outer (func2 ):
def inner (*args, **kwargs ):
user_name = input ('请输入您的用户名>>>:' )
user_pwd = input ('请输入您的密码>>>:' )
if user_name == 'max' and user_pwd == '123' :
res = func2(*args, **kwargs)
print ('后' )
return res
else :
print ('用户名或密码错误' )
return inner
func2 = outer(func2)
res = func2(1 , 2 , 3 )
print (res)
"""
如果想要被装饰的函数执行并且有返回值,那么被装饰的函数和普通函数一样都要有函数名加括号、并且赋值给一个变量名,打印。
"""
7.装饰器语法糖
语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数点用
def outer (func ):
def inner (*args, **kwargs ):
print ('代码执行前的操作' )
res = func(*args, **kwargs)
print ('代码执行后的操作' )
return res
return inner
@outer
def index ():
print ('我是index的函数体代码' )
return '我是index的返回值'
res = index()
print (res)
8.多层语法糖
def outter1 (func1 ):
print ('加载了outter1' )
def wrapper1 (*args, **kwargs ):
print ('执行了wrapper1' )
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outter2 (func2 ):
print ('加载了outter2' )
def wrapper2 (*args, **kwargs ):
print ('执行了wrapper2' )
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outter3 (func3 ):
print ('加载了outter3' )
def wrapper3 (*args, **kwargs ):
print ('执行了wrapper3' )
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outter1
@outter2
@outter3
def index ():
print ('from index' )
index()
'''
加载了outter3
加载了outter2
加载了outter1
执行了wrapper1
执行了wrapper2
执行了wrapper3
from index
'''
9.有参装饰器
def outer (mode ):
def login_auth (func ):
def inner (*args, **kwargs ):
print ('func' ,func)
print ('args' ,args)
print ('kwargs' ,kwargs)
if mode == '1' :
print ('数据直接直接写死' )
if mode == '2' :
print ('数据来源于文本' )
if mode == '3' :
print ('数据来源于字典' )
if mode == '4' :
print ('数据来源于mySQL' )
func()
return inner
return login_auth
@outer('1' )
def index ():
print ('from index' )
index()
10.装饰器模板
常用模板:两层装饰器
def outer (func ):
def inner (*args, **kwargs ):
user_name = input ('请输入您的用户名>>>>' )
user_pwd = input ('请输入您的密码>>>:' )
if user_name == 'jason' and user_pwd == '123' :
res = func(*args, **kwargs)
return res
else :
print ('用户名或密码错误' )
return inner
@outer
def index ():
print ('登录成功' )
index()
三层装饰器:外面再套一层mode
def index (mode ):
def outer (func ):
def inner (*args, **kwargs ):
user_name = input ('请输入您的用户名>>>:' )
user_pwd = input ('请输入您的密码>>>:' )
if user_name == 'jason' and user_pwd == '123' :
res = func(*args, **kwargs)
return res
return inner
return outer
@index('1' )
def func1 ():
print ('登陆成功' )
func1()
11.递归函数
1. 直接调用
def index ():
print ('from index' )
index()
index()
2. 间接调用
def index ():
print ('from index' )
func()
def func ():
print ('from func' )
index()
index()
3. 最大递归深度:python解释器添加的安全措施,官网提供的最大递归深度为1000 ,测试时出现996 -1000 都属于正常
count = 0
def index ():
global count
count += 1
print (count)
index()
index()
12.作业装饰器修复技术
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
func()
1. 编写一个用户认证装饰器
函数:register login transfer withdraw
基本要求
执行每个函数的时候必须先校验身份 eg: jason 123
def outer (func ):
def inner (*args, **kwargs ):
user_name = input ('请输入您的用户名>>>:' ).strip()
user_pwd = input ('请输入您的密码>>>:' ).strip()
if user_name == 'jason' and user_pwd == '123' :
print ('登陆成功' )
res = func(*args, **kwargs)
return res
else :
print ('用户名或密码错误' )
return inner
@outer
def register ():
print ('注册功能' )
@outer
def login ():
print ('登录功能' )
@outer
def transfer ():
print ('转账功能' )
@outer
def withdraw ():
print ('提现功能' )
register()
login()
transfer()
withdraw()
拔高练习(有点难度)
执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
提示:全局变量 记录当前用户是否认证
is_login = False
def outer (func ):
def inner (*args, **kwargs ):
global is_login
if is_login:
res = func(*args, **kwargs)
return res
user_name = input ('请输入您的用户名>>>:' ).strip()
user_pwd = input ('请输入您的密码>>>:' ).strip()
if user_name == 'jason' and user_pwd == '123' :
print ('登陆成功' )
is_login = True
res = func(*args, **kwargs)
return res
else :
print ('用户名或密码错误' )
return inner
@outer
def register ():
print ('注册功能' )
@outer
def login ():
print ('登录功能' )
@outer
def transfer ():
print ('转账功能' )
@outer
def withdraw ():
print ('提现功能' )
register()
login()
transfer()
withdraw()
2. 利用有参装饰器编写多种用户登录校验策略
def login_auth (mode ):
def outer (func ):
def inner (*args, **kwargs ):
user_name = input ('请输入您的用户名>>>:' ).strip()
user_pwd = input ('请输入您的密码>>>:' ).strip()
if mode == 'absolute' :
if user_name == 'jason' and user_pwd == '123' :
print ('登陆成功' )
res = func(*args, **kwargs)
return res
else :
print ('用户名或密码错误' )
elif mode == 'type_list' :
user_list = ['jason|123' ,'kevin|321' ,'tony|222' ]
user_data = f'{user_name} |{user_pwd} '
if user_data in user_list:
print ('登陆成功' )
res = func(*args, **kwargs)
return res
else :
print ('登陆失败' )
elif mode == 'type_file' :
with open (r'userinfo.txt' , 'r' , encoding='utf8' ) as f1:
for line in f1:
real_name, real_pwd = line.split('|' )
if user_name == real_name and user_pwd == real_pwd.strip('\n' ):
print ('登陆成功' )
res = func(*args, **kwargs)
return res
else :
print ('用户名或密码错误' )
return inner
return outer
@login_auth('absolute' )
def index (*args, **kwargs ):
print ('from index' )
@login_auth('type_list' )
def func (*args, **kwargs ):
print ('from func' )
@login_auth('type_file' )
def foo (*args, **kwargs ):
print ('from index' )
3. 利用递归函数依次打印列表中每一个数据值
l1 = [1 ,[2 ,[3 ,[4 ,[5 ,[6 ,[7 ,[8 ,]]]]]]]]
l1 = [1 ,[2 ,[3 ,[4 ,[5 ,[6 ,[7 ,[8 ,]]]]]]]]
def index (x ):
for i in x:
if type (i) is int :
print (i)
else :
index(i)
index(l1)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律