昨日内容回顾
-
global与nonlocal关键字
global 用于局部名称空间修改全局名称空间中的名字绑定关系 nonlocal 用于局部名称空间修改外层局部名称空间中的名字绑定关系
-
函数名的多种用法
1.函数名可以当做变量名被赋值 def index(): print('from index') res = index 2.函数名可以当做函数的实参 def func(a): print(a) func(123) # a = 123 func(index) # a = index 3.函数名可以当做函数的返回值 def foo(): def inner(): print('from inner') return inner res = foo() # res = inner 4.函数名还可以当做容器类型的数据值 func_dict = {'1':index,'2':func}
-
闭包函数
1.定义在函数内部的函数 2.使用了外部函数名称空间中的名字 def inner(name): print(name) def outer(name): # name = 'jason' def inner(): print(name) return inner res = outer('jason') # res = inner res() # inner()
-
装饰器前戏
1.不改变被装饰对象源代码 2.不改变被装饰对象调用方式 给被装饰对象添加新的功能 时间相关操作 import time time.time() time.sleep()
-
装饰器推导流程
1.统计函数的执行时间 def index(): print('from index') start_time = time.time() index() print(time.time() - start_time) 2.由于index函数可能需要在很多地方执行 代码反复编写不好 考虑封装成函数 def get_time(): start_time = time.time() index() print(time.time() - start_time) 3.上述代码只能统计index函数的执行时间 局限性太强 应该让该名字动起来 def get_time(xxx): start_time = time.time() xxx() print(time.time() - start_time) 4.上述直接封装形参传值不写 所以只能考虑闭包函数 def outer(xxx): def get_time(a): start_time = time.time() xxx(、、、、、、、、、、、、) print(time.time() - start_time) return get_time res = outer(index) # res = get_time index = outer(index) # index = get_time index() 5.上述装饰器只能装饰无参函数兼容性不好 def func(a): print('from func', a) func(123) # 正确 func = outer(func) func(123) # 报错 推导可得被装饰的函数需要几个参数get_time就应该加几个参数 def outer(xxx): def get_time(*args, **kwargs): start_time = time.time() xxx(*args, **kwargs) print(time.time() - start_time) return get_time 6.被装饰对象返回值无法获取 def outer(xxx): def get_time(*args, **kwargs): start_time = time.time() ret = xxx(*args, **kwargs) print(time.time() - start_time) return ret return get_time func = outer(func) res = func(123)
-
装饰器模板
def outer(func_name): def inner(*args, **kwargs): '''执行被装饰对象之前可以做的额外操作''' res = func_name(*args, **kwargs) '''执行被装饰对象之后可以做的额外操作''' return res return inner
-
装饰器语法糖
@outer # register = outer(register) def register(): pass @outer # login = outer(login) def login(): pass register() login() """ 自动将紧挨着语法糖下面的名字当做参数传递给@后面的函数并调用 """
今日内容概要
- 作业讲解
- 多层语法糖问题
- 有参装饰器
- 装饰器修复技术
- 递归函数
- 算法之二分法
今日内容详细
作业讲解
1.编写一个用户认证装饰器
函数:register login transfer withdraw
基本要求
执行每个函数的时候必须先校验身份 eg: jason 123
拔高练习(有点难度)
执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
提示:全局变量 记录当前用户是否认证
# 定义一个变量记录用户的登录状态
is_login = False
def login_auth(func_name):
def inner(*args, **kwargs):
global is_login
# 先判断全局名称空间中的变量名is_login绑定的值是否为True
if is_login:
res = func_name(*args, **kwargs)
return res
username = input('username>>>:').strip()
password = input('password>>>:').strip()
if username == 'jason' and password == '123':
# 将全局名称空间中记录用户登录状态的数据值该为True
is_login = True
res = func_name(*args, **kwargs)
return res
else:
print('用户名或密码错误无法执行函数')
return inner
@login_auth
def register():
print('注册功能')
@login_auth
def login():
print('登录功能')
@login_auth
def shopping():
print('购物功能')
register()
login()
shopping()
多层语法糖
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 = outter1(wrapper2)
"""
有参装饰器
# 校验用户是否登录装饰器
def outer(mode):
def login_auth(func_name):
def inner(*args, **kwargs):
username = input('username>>>:').strip()
password = input('password>>>:').strip()
if mode == '1':
print('数据直接写死')
elif mode == '2':
print('数据来源于文本文件')
elif mode == '3':
print('数据来源于字典')
elif mode == '4':
print('数据来源于MySQL')
return inner
return login_auth
'''当装饰器中需要额外的参数时>>>:有参装饰器'''
"""
函数名加括号执行优先级最高 有参装饰器的情况
先看函数名加括号的执行
然后再是语法糖的操作
"""
# @outer('1')
def index():
print('from index')
index()
# @outer('2')
def func():
print('from func')
func()
装饰器模板
# 最常用的无参装饰器
# def outer(func_name):
# def inner(*args, **kwargs):
# res = func_name(*args, **kwargs)
# return res
# return inner
# @outer
# def index():
# pass
# 不常用的有参装饰器
# def outer_plus(mode):
# def outer(func_name):
# def inner(*args, **kwargs):
# res = func_name(*args, **kwargs)
# return res
# return inner
# return outer
# @outer_plus('MySQL')
# def func():
# pass
装饰器修复技术
# def index():
# """index函数 非常的牛"""
# pass
# help(index)
# help(len)
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(1) = 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,]]]]]]]]
2.整理今日内容及博客
3.利用有参装饰器编写多种用户登录校验策略
标签:index,return,第十三,python,---,func,time,print,def
From: https://www.cnblogs.com/tengyifan888/p/16785532.html