python装饰器与递归函数

博客围绕Python展开,介绍了装饰器和递归函数。装饰器完美诠释开放封闭原则,可在不改变原函数源码及调用方式下增加额外功能,还提及被装饰函数带返回值、参数等情况。递归函数是在内部调用自己,在某些场景有奇效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

装饰器

1.开放封闭原则

软件面世时,不可能把所有的功能都设计好,当前的未来一两年功能给你上线,定期更新迭代。对于软件之前的写的源代码一般都不会修改,对函数里面的代码以及函数的调用方式。

封闭原则: 不要改变源码。

开放原则:更新增加一些额外的功能。

python中装饰器:完美的诠释的开放封闭原则。

装饰器就是一个函数: 他要装饰一个函数,在不改变原函数的源码以及调用方式的前提下,给其增加一个额外的功能。

2.初识装饰器

# 装饰器函数
def test_time(x):  # x = index
    def inner():
        start_time = time.time()
        x()
        end_time = time.time()
        print(f'此函数的执行效率{end_time-start_time}')
    return inner

@test_time  #与在下面写 index = test_time(index) 效果一样
def index():
    time.sleep(2)
    print('欢迎访问博客园首页')

# index = test_time(index) # 运行效果 index = inner
index() # 此时 index() 在执行 inner 函数

@test_time
def func1():
    time.sleep(2)
    print('欢迎访问日记首页')

@test_time
def func2():
    time.sleep(1)
    print('欢迎访问评论首页')

# func1 = test_time(func1)  #麻烦 每个函数下面都要改函数名 推荐用@
# func1 = test_time(func1)
func1()
func2()

3.被装饰函数带返回值

def test_time(x):  # x = index
    def inner():
        start_time = time.time()
        ret = x()
        end_time = time.time()
        print(f'此函数的执行效率{end_time-start_time}')
        return ret # 返回index() 的返回值给 inner()
    return inner

@test_time  # index = test_time(index)
def index():
    time.sleep(0.5)
    print('欢迎访问博客园首页')
    return True

print(index())  # inner()
# 你应该是让True返回给index()这样才完美了,但是现在index是inner,所以你要是完全不改变原函数的使用,
# 你print(index()) ---> True

4.被装饰函数带参数

# 被装饰函数带参数,无论加不加装饰器,你的实参都应该传给形参。
# 但以上的版本不能实现传参,index('太白金星') == inner('太白金星')
def test_time(x):  # x = index
    def inner(*args,**kwargs):
        # 函数的定义:* ** 聚合。
        # args = ('苹果',)
        #args = (1, 3)
        start_time = time.time()
        ret = x(*args,**kwargs)
        # 函数的执行:* ** 打散。
        # ret = x(*('苹果',))  ==x('苹果')
        # ret = x(*(1, 3))  ==x(1,3)
        end_time = time.time()
        print(f'此函数的执行效率{end_time-start_time}')
        return ret
    return inner

@test_time  # index = test_time(index)
def index(n):
    time.sleep(0.5)
    print(f'欢迎{n}访问博客园首页')
    return True

@test_time  # index = test_time(index)
def func2(a,b):
    time.sleep(0.5)
    print(f'最终结果:{a+b}')
    return a + b
print(index('苹果'))  # inner('苹果')
print(func2(1,3)) # == inner(1,3)

5.标准版装饰器

def warpper(f): # 标准装饰器模板
    def inner(*args,**kwargs):
        '''被装饰函数之前的操作'''
        # print(666)
        ret = f(*args,**kwargs)
        '''被装饰函数之后的操作'''
        # print('执行完毕了')
        return ret
    return inner

@warpper # 调用
def func():
    print(111)

6.带参数的装饰器

def wrapper_out(n,*args,sex='男',):
    def wrapper(f):  # f = func1
        def inner(*args,**kwargs):
            ret = f(*args,**kwargs)  # func1()
            return ret
        return inner
    return wrapper

def func1():
    print('in func1')
func = wrapper_out(1)  # 返回值是wrapper函数名
ly = func(func1)  # 等于wrapper(func1) = inner 返回值
ly()  # 等于inner()

# 使两个函数通过装饰器传参打开两个不同的文件
def wrapper_out(n):
    def wrapper(f):
        def inner(*args,**kwargs):
            username = input('请输入用户名:').strip()
            password = input('请输入密码:').strip()
            with open(n,encoding='utf-8') as f1:
                for line in f1:
                    user,pwd = line.strip().split('|')
                    if username == user and password == pwd:
                        print('登陆成功')
                        ret = f(*args,**kwargs)
                        return ret
                return False
        return inner
    return wrapper
"""
@wrapper_out('qq')
def qq():
    print('成功访问qq')
qq()
看到带参数的装饰器分两步执行:
@wrapper_out('腾讯')
    1. 执行wrapper_out('腾讯') 这个函数,把相应的参数'腾讯' 传给 n,并且得到返回值 wrapper函数名。
    2. 将@与wrapper结合,得到我们之前熟悉的标准版的装饰器按照装饰器的执行流程执行。
"""
@wrapper_out('qq')
def qq():
    print('成功访问qq')

@wrapper_out('tiktok')
def tiktok():
    print('成功访问抖音')

qq()
tiktok()
# 开发思路:增强耦合性

7.多个装饰器装饰一个函数

def wrapper1(func1):  # func1 = f原函数
    def inner1():
        print('wrapper1 ,before func')  # 2
        func1()
        print('wrapper1 ,after func')  # 4
    return inner1

def wrapper2(func2):  # func2 == inner1
    def inner2():
        print('wrapper2 ,before func')  # 1
        func2()  # inner1
        print('wrapper2 ,after func')  # 5
    return inner2

@wrapper2  # f = wrapper2(f) 里面的f == inner1  外面的f == inner2
@wrapper1  # f = wrapper1(f) 里面的f == func1  外面的 f == inner1
def f():
    print('in f')  # 3

f()  # inner2()

# 从上往下执行函数前的操作,从下往上执行函数后的操作,中间执行函数

递归函数

递归函数:函数或者其他代码都可以解决递归解决的问题,但是递归在某些时候能出奇制胜的效果

通俗点说,就是函数在自己内部调用自己。

递归函数举例

# 初识递归。
def func(n):
    print(n)
    n += 1
    func(n)
func(1)

# 官网规定:默认递归的最大深度1000次。
# 如果你递归超过100次还没有解决这个问题,那么执意使用递归,效率很低。

'''
下边的每一个人都比上一个大两岁,计算第四个人的年龄
1  太白   18
2  景女神  18 + 2
3  宝元    18 + 2 + 2
4  alex    18 + 2+ 2+2  age(4) = age(3) + 2
'''

def age(n):
    if n == 1:
        return 18
    else:
        return age(n-1) + 2
print(age(4))
'''递归内部运算
def age(4):
    if n == 1:
        return 18
    else:
        return age(3) + 2

age(4) = age(3)  + 2

def age(3):
    if n == 1:
        return 18
    else:
        return age(2) + 2
age(4) = age(2) + 2  + 2


def age(2):
    if n == 1:
        return 18
    else:
        return age(1) + 2
age(4) = age(1) + 2 + 2  + 2    

def age(1):
    if n == 1:
        return 18
    else:
        return age(1) + 2

age(4) = 18 + 2 + 2  + 2    
'''

l1 = [1, 3, 5, ['太白','元宝', 34,],66]
# 将l1以下面的形式展现在屏幕上
'''
1
3
5
'太白'
'元宝'
34
66
'''
l1 = [1, 3, 5, ['太白','元宝', 34,],66]
# 利用双层for循环
for i in l1:
    if type(i) == list:
        for j in i:
            print(j)
    else:
        print(i)
# 但如果列表嵌套的层数比较多,需要多层for循环,代码重复性高,这时就可以用递归

# 递归函数
def func(alist):
    for i in alist:
        if type(i) == list:
            func(i)  # func(['太白','元宝',34])
        else:
            print(i)
func(l1)
# 这样无论列表嵌套多少层,这个函数都能解决

转载于:https://www.cnblogs.com/changyifei-8/p/11078137.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值