装饰器复杂使用

昨日内容回顾

  • 闭包函数
定义在函数内部的函数并且使用了外包函数局部名称空间中的名字
闭包函数给我们提供了另外一种传参方式
  • 装饰器简介
装饰器不改变源代码不改变被装饰对象调用方式才能称为装饰器
  • 装饰器的推倒流程
1.统计某个函数的运行时间
2.将统计函数运行时间的代码封装成函数
3.直接封装的函数会改变调用方式
4.利用闭包函数传参尝试
5.利用重名替换原来的函数名的功能
6.函数的参数
7.函数的返回值
  • 装饰器的模版
def outer(func_name)
	def inner(*args,**kwargs)
  res = func_name(*args,**kwargs)  # 这个就是被装饰函数执行的地方
  return res
return inner  #此处返回值需是组成装饰器第二个函数
"""
针对两个地方的*args和**kwargs的作用
def index(*args,**kwargs):
	pass

def func(*args,**kwargs):
	index(*args,**kwargs)

func([1,2,3,4],name='jason',age=18)
"""
  • 装饰器语法糖
@后面跟第一个定义的函数包装饰器第一个函数
def home():
 		pass
 honme= outer(home)
 home()
  • 装饰器修复技术
from functools import wraps
def outer(func_name):
  @wraps(func_name)
  def inner(*args, **kwargs):
    print('jason')
    res = func_name(*args, **kwargs)
    print('tony')
    return res
  return inner
@outer
def user_name():
  print('kiven')
 user_name()

今日内容概要

  • 多层装饰器
  • 有参装饰器
  • 递归函数
  • 算法
  • 三元表达式

今日内容详细

升级版作业

is_login = {'is_login': False}  #1.定义状态栏

from functools import wraps  # 装饰器修复技术
def login_auth(func_name):  # 2.编写装饰器
    @wraps(func_name)
    def inner(*args,**kwargs):  #4.装饰器二层函数使用第一层函数返回值调用
        if is_login.get('is_login'):  # 按k取 如果成立则不走下面代码直接执行被装饰函数然后结束
            res = func_name(*args, **kwargs)  # 被装饰函数调用位置
            return res  #被调用函数调用后返回值
        user_name = input('输入用户名>>>:').strip()  # 6.获取用户输入
        pwd = input('输入用户密码>>>:').strip()  #7.
        if user_name == 'jason' and pwd == '123':  #8.
            res = func_name(*args, **kwargs)  #9.  被装饰函数执行
            is_login['is_login'] = True  # 10.校验成功一次后会将字典中的值改为成立
            return res  #11. 这是被装饰函数的返回值没有return此时返回值为None
        else:
            print('权限不足')
    return inner  #5.返回函数名到外部 此时外层调用的函数是inter函数
@login_auth
def register():  #3.调用函数
    print('注册功能')
@login_auth
def login():
    print('登陆功能')
@login_auth
def transfer():
    print('转账功能')
@login_auth
def withdraw():
    print('提现功能')
register()  # inter函数
login()
transfer()
withdraw()
print(register())  # 内层函数处返回的是函数名便可以使用 如果返回的不是
                   # 被装饰函数名则这个返回值是被包函数的返回值被函数就
                   #第二层函数,被装饰函数是下面定义的函数有装饰语法糖的函数

多层装饰器

def outter1(func1):
    print('加载了outter1')
    def wrapper1(*args, **kwargs):  #1  wrapper1
        print('执行了wrapper1')
        res1 = func1(*args, **kwargs)  #2  wrapper2
        return res1
    return wrapper1  # index

def outter2(func2):
    print('加载了outter2')
    def wrapper2(*args, **kwargs):  #  3
        print('执行了wrapper2')
        res2 = func2(*args, **kwargs)  #4
        return res2
    return wrapper2

def outter3(func3):  # 1
    print('加载了outter3')
    def wrapper3(*args, **kwargs):# 5
        print('执行了wrapper3')
        res3 = func3(*args, **kwargs) #6
        return res3
    return wrapper3

# @outter4  # index = outter4(wrapper1)  index是wrapper1
@outter1  # index = outter1(wrapper2)
@outter2  # wrapper2 = outter2(wrapper3)
@outter3  # wrapper3 = outter3(index)
def index():
    print('from index')
index()  #此调用为wrapper1

有参函数

def login_auth(func_name):
    def inner(*args, **kwargs):
        username = input('username>>>:').strip()
        password = input('password>>>:').strip()
        if username == 'jason' and password == '123':
            res = func_name(*args, **kwargs)
            return res
        else:
            print('用户权限不够 无法调用函数')
    return inner

"""
需求:在装饰器内部可以切换多种数据来源
	列表
	字典
	文件
"""
def outer(condition,type_user):
    def login_auth(func_name):  # 这里不能再填写其他形参
        def inner(*args, **kwargs):  # 这里不能再填写非被装饰对象所需的参数
            username = input('username>>>:').strip()
            password = input('password>>>:').strip()
            # 应该根据用户的需求执行不同的代码
            if type_user =='jason':print('VIP')
            if condition == '列表':
                print('使用列表作为数据来源 比对用户数据')
            elif condition == '字典':
                print('使用字典作为数据来源 比对用户数据')
            elif condition == '文件':
                print('使用文件作为数据来源 比对用户数据')
            else:
                print('去你妹的 我目前只有上面几种方式')
        return inner
    return login_auth
@outer('文件','jason')
def index():
    print('from index')
index()
"""
我们以后遇到的最复杂的装饰器就是上面的 不会比上面更复杂 
目的仅仅是为了给装饰器代码传递更多额外的数据
"""

递归函数

概念
函数直接或间接调用直接
# 递归调用,直接调用
def index()
	print('from index
  index()



#简介调用
def index()
	print('from index')
  func()
def func()
	print('from func')
  index()
 
        
func()        
'''
python中允许函数最大递归调用次数
官方给出是1000 用代码验证是996 或 997
有偏差



'''  
 
count = 0
def func():
    print('from func')
    global count
    count += 1
    print(count)
    index()
def index():
    print('from index')
    func()

index()


# import sys
#
# sys.setrecursionlimit(2000)  修改递归调用次数
#
# print(sys.getrecursionlimit())  查询递归次数
#        
"""
递归函数真正的应用场景
    递推:一层层往下寻找答案
    回溯:根据已知条件推导最终结果
递归函数
    1.每次调用的时候都必须要比上一次简单!!!
    2.并且递归函数最终都必须要有一个明确的结束条件!!!
"""
 l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]       
 # 循环打印出列表中所有的数字
# 1.for循环l1里面所有的数据值
# 2.判断当前数据值是否是数字 如果是则打印
# 3.如果不是则继续for循环里面所有数据值
# 4.判断当前数据值是否是数字 如果是则打印
# 5.如果不是则继续for循环里面所有数据值
# 6.判断当前数据值是否是数字 如果是则打印   
def get_num(l1):  
    for i in l1:
        if isinstance(i,int):
            print(i)
        else:
            get_num(i)
get_num(l1)


image

算法二分法

什么是算法
	算法就是解决问题的方法
算法永远都在精进 但是很少有最完美的算法
	算法很多时候可能没什么用
    	小公司一般不会有算法工程师 只有大公司才会有
   			算法工程师待遇很高 但是产出很少 甚至几年几十年都没有成果
          有点相当于科研人员
很多大型互联网面试都喜欢问算法
	平时学有余力可以简单看看(临时抱佛脚)
    	二分法 快拍 插入 堆排 链表 双向链表 约瑟夫问题
二分法
	是所有算法里面最简单的算法
    	也有人说二分法不是算法
        
l1 = [11, 23, 32, 45, 65, 78, 90, 123, 432, 467, 567, 687, 765, 876, 999, 1131, 1232]


def get_num(l1, target_num):
    # 添加递归函数的结束条件
    if len(l1) == 0:
        print('不好意思 找不到')
        return
    # 1.先获取数据集中间那个数
    middle_index = len(l1) // 2
    middle_value = l1[middle_index]
    # 2.判断中间的数据值与目标数据值孰大孰小
    if target_num > middle_value:
        # 3.说明要查找的数在数据集右半边  如何截取右半边
        right_l1 = l1[middle_index + 1:]
        # 3.1.获取右半边中间那个数
        # 3.2.与目标数据值对比
        # 3.3.根据大小切割数据集
        # 经过分析得知 应该使用递归函数
        print(right_l1)
        get_num(right_l1, target_num)
    elif target_num < middle_value:
        # 4.说明要查找的数在数据集左半边  如何截取左半边
        left_l1 = l1[:middle_index]
        # 4.1.获取左半边中间那个数
        # 4.2.与目标数据值对比
        # 4.3.根据大小切割数据集
        # 经过分析得知 应该使用递归函数
        print(left_l1)
        get_num(left_l1, target_num)
    else:
        print('找到了', target_num)


# get_num(l1, 999)
get_num(l1, 1000)

"""
二分法缺陷
	1.数据集必须是有序的
	2.查找的数如果在开头或者结尾 那么二分法效率更低!!!
"""
l1 = [11, 23, 32, 45, 65, 78, 90, 123, 432, 467, 567, 687, 765, 876, 999, 1131, 1232]  # 定义列表

# 先获取数据中间的数据
def func(l1,tanger_num):
    if len(l1) == 0:  # 如果切到为0无法切直接结束
        print('木有你要找到数字')
        return
    num = len(l1)//2  # len出数据个数一分为二 索引位数
    index_num = l1[num]  #取到索引中间的一个数
    if tanger_num > index_num:  # 拿我们要的数据值和拿到的数据做比对 如果da说明数据在右边
        right_l1 = l1[num+1:]  # 将列表一分为二 列表索引个数加一从索引位数出加一冒号切到末尾
        print(right_l1)  
        func(right_l1,tanger_num)  # 再次调用函数 将切割后的列表当参数传入将比对的数据也传入再走一次流程
    elif tanger_num < index_num:
        left_l1 = l1 [:num]
        print(left_l1)
        func(left_l1,tanger_num)
    else:
        print('找到了',tanger_num)
func(l1,8999)

image

作业


data_dict = {'name': 'kiven', 'pwd': 123}
user_name_list = ['jason|123']
print('''
1.列表
2.字典
3.文件
''')
func_id = input('输入数据认证类型').strip()
def data(chonie):
    def ohter(user_name_info):
        def func(*args, **kwargs):
            user_name = input('请输入用户名>>>:').strip()
            password = input('请输入密码>>>:').strip()
            if chonie == '1':
                real_name, realpwd = user_name_list[0].split('|')
                if user_name == real_name and password == realpwd:
                    onglin = user_name_info(*args, **kwargs)
                    return onglin
                else:
                    print('认证失败')
            elif chonie == '2':
                real_name = data_dict.get('name')
                real_pwd = data_dict.get('pwd')
                real_pwd = str(real_pwd)  # 未转字符串比对就会打印多出一步
                if user_name == real_name and password == real_pwd:  # 密码是字符串 字典里的是整型
                    onglin = user_name_info(*args, **kwargs)
                    return onglin
                else:
                    print('认证失败')
            elif chonie == '3':
                with open(r'a.txt', 'r', encoding='utf8') as f:
                    k = f.read()
                real_name, real_pwd = k.split('|')
                if user_name == real_name and password == real_pwd:
                    onglin = user_name_info(*args, **kwargs)
                    return onglin
                else:
                    print('认证失败')
            else:
                print('没有此数据')
        return func
    return ohter
@data(func_id)
def onglin():
    print('认证成功')
onglin()
posted @ 2022-07-07 00:40  懒羊羊A  阅读(36)  评论(0)    收藏  举报