装饰器深入 、递归函数入门

多层语法糖

def outter1(func1):
    def wrapper1(*args, **kwargs):
        print('前处理')
        res = func1(*args, **kwargs)
        print('后处理')
        return res

    return wrapper1
def outter2(func1):
    def wrapper2(*args, **kwargs):
        print('前处理')
        res = func1(*args, **kwargs)
        print('后处理')
        return res

    return wrapper2
def outter3(func1):
    def wrapper3(*args, **kwargs):
        print('前处理')
        res = func1(*args, **kwargs)
        print('后处理')
        return res

    return wrapper3


@outter1  # outter1(wrapper2)
@outter2  # outter2(wrapper3)
@outter3  # outter3(真正的index) ——> wrapper3
def index():
    print('miku')
index()

输出结果:
image

推导过程

image

有参装饰器 (补充)

def outer_plus(mode): # 传到这里的形参
    def outer(func_name):
        def inner(*args, **kwargs):
            print(mode)  # 这里可以用传进来的参数
            res = func_name(*args, **kwargs)
            return res
        return inner
    return outer
@outer_plus('在括号里传参数') 
def func():
    pass
# 请注意:
# 函数名+括号的优先级最高
# 所以outer_plus()这个函数会优先执行 此时先忽略语法糖的@
# outer_plus()运行结束返回一个outer 然后语法糖再发挥功能 @outer 将func传入outer

装饰器修复技术(了解)

装饰器修复只是为了让装饰器‘装’的更像!

# 1.这是一个经典的装饰器
def outer(func_name):
    def inner(*args, **kwargs):
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def index():
    pass
# 2.通过help方法查看index到底是什么
help(index)
# 结果如下:可见通过help函数可以知道index实际是指向inner函数 ps:被识破了吗 ~

image

# 3.想办法骗过help函数
from functools import wraps  # 首先这里导个包

def outer(func_name):
    @wraps(func_name) # 在这里添加一行代码
    def inner(*args, **kwargs):
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def index():
    pass

help(index) # 大功告成! 现在help也无法识破了 装的非常像了 是一个优雅的装饰器=。=
# 运行如下: ps:装再怎么像 实际上还是在运行inner

image

递归函数

前戏

image

# 函数自己调用自己会发生什么?
# 1.直接调用
def index():
    print('from index')
    index()
index()
# 会报错:RecursionError: maximum recursion depth exceeded while calling a Python object
# python限制默认调用自己的次数为1000次 # 一直调用自己就强制报错 # 这也是一种保护机制
# JAVA没有这种限制 # 越晚出来的编程语言 考虑越周到 # 以后可能出来新的编程语言 吸收各种编程语言的优点
# 2.间接调用
def index():
    print('from index')
    func()

def func():
    print('from func')
    index()
func() # 你调用我 我调用你 老样子还是报错 因为调用次数太多了
# 3.看一下到底调用了多少次!
count = 0
def index():
    global count
    count += 1
    print(count)
    index()
index()
    '''官网提供的最大递归深度为1000 我们在测试的时候可能会出现996 997 998'''
# 4.补充一点 修改python默认的递归深度
import sys  # 导入sys模块
sys.setrecursionlimit(3000)  # 修改默认的递归深度为3000次

递归函数概念

image

1.递归函数概念
	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 # 这里会一直调用get_age  # 函数调用的优先级比return高
    res = get_age(5)
    print(res)

练习

'''
1.利用递归函数依次打印列表中每一个数据值
	l1 = [1,[2,[3,[4,[5,[6,[7,[8,]]]]]]]]
'''

l1 = [1, [2, [3, [4, [5, [6, [7, [8, ]]]]]]]]


# 思路
# 先不用递归函数 先想正常取值怎么把每个值都取出来 然后用递归函数实现
# a = l1.pop()  # 弹出第末尾元素
# print(a)  # 输出弹出的值
# print(l1[0]) # 原列表就剩下一个 1 输出它
# b = a.pop()  # 弹出a末尾的值
# print(a[0]) # 输出a列表的第一个值 2


def recursion(depth_list):  # 传入一个列表

    if len(depth_list) == 1:
        print(depth_list[0])
        return
    else:
        list_swap = depth_list.pop()
        print(depth_list[0], end=' ')
    return recursion(list_swap)


recursion(l1)


'''2.有参装饰器编写多种用户登录校验策略'''

# 多种登录应该对应的是 邮箱登录 QQ登录 微信登录 手机号登录


# 模式一直接校验
# 模式二用列表存数据

userdata_list = ['jason|123', 'kevin|321', 'oscar|222']


def outer_plus(mode):
    def outer(func_name):
        def inner(*args, **kwargs):
            while True:
                if mode == '1':  # 数据值写死
                    while True:
                        username = input('请输入用户名>>>')
                        password = input('请输入密码>>>')
                        if username == 'miku' and password == '123':
                            res = func_name(*args, **kwargs)
                            return res
                        else:
                            print('模式1认证失败')
                elif mode == '2':  # 列表存储数据的情况
                    while True:
                        username = input('请输入用户名>>>')
                        password = input('请输入密码>>>')
                        for one_user in userdata_list:
                            one_name, one_password = one_user.split('|')
                            if username == one_name and password == one_password:
                                res = func_name(*args, **kwargs)
                                return res
                            else:
                                print('模式2认证失败')
                elif mode == '3':  # 文件存储数据的情况
                    username = input('请输入用户名>>>').strip()
                    password = input('请输入密码>>>').strip()
                    with open('userinfo.txt', 'r', encoding='utf8') as f:
                        for line in f:
                            line.strip('\n')
                            one_name, one_password = line.split(':')
                            if username == one_name.strip() and password == one_password.strip():  # 有隐藏的空格
                                res = func_name(*args, **kwargs)
                                return res
                        else:
                            print('文件中没有此用户')
                else:
                    print('=。=')
                    return

        return inner

    return outer


mode_def = input('''
1.直接验证
2.列表存数据
3.文件存数据
>>> 请输入数字:
''').strip()


@outer_plus(mode_def)
def func():
    print('我是func 我执行了哈哈哈')


func()
posted @ 2022-10-12 17:24  passion2021  阅读(56)  评论(0编辑  收藏  举报