进入python的世界_day13_python基础——函数之有参装饰器、装饰器修复、递归函数

写在开头:最近几天的知识很抽象,牢记以下几点

​ 1.走到哪一步就看哪一步,碰到一个函数,如果没执行调用,就看成一行代码,函数体代码没执行调用可以先不看

​ 2.作用域关系是在函数定义阶段就确定好了的,全局绑一个变量名局部都可以用

​ 3.碰到名字+括号,在该域中先运行

一、叠加多层语法糖 ——用结论去找答案

结论:

​ 叠加多个装饰器语法糖

  1. 加载顺序(outter函数的调用顺序):自下而上
  2. 执行顺序(wrapper函数的执行顺序):自上而下
无参装饰器1模板
无参装饰器2模板
无参装饰器3模板


@outter1>>>index=outter1(warpper2的内存地址) >index=wrapper1的内存地址

@outter2>>>index=outter2(warpper3的内存地址)>index=wrapprer2的内存地址

@outter3  >>>index=outter3(index)>>>index=wrapper3的内存地址

def index():

	print('from index')
	
   因为语法糖是将正下方贴贴着的函数的内存地址,当作参数传过来,所以加载时从outter3加载,然后一层层给上方的语法糖传参>>>可以理解为从下往上装饰三次

二、有参装饰器

​ 无参装饰器只能接收一个参数,并且还是函数类型,所以想给装饰器传指定参数就得把装饰器再包一次,让最外面的函数接受参数,返回装饰器的函数体内存地址

语法格式: @装饰器(参数,...)

def 有参装饰器(mode):
	def 无参装饰器(func):
		def wrapper(*args, **kwargs):
			res = func(*args, **kwargs)
			return res 
		return wrapper
	retun 无参装饰器 
	
@有参装饰器(1):
def 被装饰对象():
	pass 

碰到有参装饰器调用执行就是@后面的函数先调一下,得一个结果再跟@联动

第一层被装饰函数体本身,第二层套闭包,要用语法糖,但是只能传函数名字进去,第三层就能转文件进去,所以没有必要第四层了,第三层没有被固定死,前两层都是受限制的

三、装饰器的修复技术(好比隐身雷达)

1.由来

​ 首先,每个函数,没被装饰前,都有自己的名字

​ 比如说

def hi1():
    pass
   

def hi2():
    pass

我们打印下这两个函数的名字:
print(hi1.__name__)
print(hi2.__name__)
>>>>
hi1
hi2
# 可以看到,他们自己有自己的名字

​ 给他们套个装饰器后呢?

def wraper(func):
    def inner(*args, **kwargs):
        return func(*args, **kwargs)
    return inner
@wraper
def hi1():
    pass
@wraper
def hi2():
    pass
print(hi1.__name__)
print(hi2.__name__)

>>>
inner
inner
# 结果都变成了inner
 
 

2.怎么用

​ >>>from functools import wraps +@wraps(func) # func不固定名字,随便写都行 @wraps(func)用在装饰器的子代码的第一行 做强调

from functools import wraps
def wraper(func):
    @wraps(func)
    def inner(*args, **kwargs):
        return func(*args, **kwargs)
    return inner
@wraper
def hi1():
    pass
@wraper
def hi2():
    pass
print(hi1.__name__)
print(hi2.__name__)

四、归递函数

1.介绍

函数的递归调用:是函数嵌套调用的一种特殊形式

具体是指:在调用一个函数的过程当中,又直接或者间接地调用到了本身

Python官方对递归调用循环调用的次数有限制,为1000次左右(可能会打断在996之类的次数)

1.自己引用自己

def hi1():
    print('你好')
    hi1()

hi1()
>>>
执行到报错

2.别人引用自己

def hi1():
    print('你好')
    hi2()

def hi2():
    print('你真好')
    hi1()

hi1()
>>>
运行到报错

​ 其实上面的两个例子,都可以用while 或者for来做到,由此我们可以知道,如果想让一段代码循环,可以再加一种方法, 这个方法就是递归函数

原则:递归不应该一直无限循环下去,应该满足某一条件就停止运行

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 # 为什么碰到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,]]]]]]]]
# l1 = [1,x]
# 我们的答案是,让得到的数据值不是列表,只要有数据还是列表,就要一直循环搞
def func(l1):
    for i in l1:
        if type(i) is list:
            # 如果是列表,应该再循环、再判断,即 重新运行本身的代码
            func(i)
        else:
            print(i)

func(l1)

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

posted @ 2022-10-12 14:35  yiwufish  阅读(467)  评论(0)    收藏  举报