Python笔记14-装饰器&递归

一、装饰器【重点掌握】

Iterable:可迭代对象

Iterator:迭代器

generator:生成器

decorator:装饰器

概念:已知一个函数,如果需要给该函数增加新的功能,但是不希望修改原函数,在Python中,这种在代码运行期间动态执行的机制被称为装饰器【Decorator】

装饰器的作用:为已经存在的函数或者类添加额外的功能

装饰器的本质:实际上就是一个闭包,内部函数访问外部函数中的变量【函数】

1.基本用法

# 1.闭包
def func1(n):
    def func2():
        print(n)
    func2()
func1(10)


def func1(n):
    def func2():
        print(n)
    return func2
f = func1(10)   # f = func2
f()

# 2.装饰器的基本语法
def test():                                             # 9
    print("拼搏到无能为力,坚持到感动自己")

# 装饰器的基本书写步骤
# a.书写闭包
# b.给外部函数设置参数,该参数表示需要被装饰的函数
def outter1(func):                                      # 2
    def inner1():                                       # 3 7
        # c.调用原函数【在内部函数中访问外部函数中的变量】
        func()     # 调用原函数test                       # 8 10
        # d.增加新的功能
        print("new~~~~")
    return inner1                                       # 4
# e.调用装饰器【外部函数】
f1 = outter1(test)    # func = test   f1 = inner1       # 1  5
# f.调用装饰器的内部函数
# print(f1)
f1()     # inner1()                                     # 6  11

# 1.原函数有参数
def get_age(age):
    print(f"年龄:{age}")

# 需求:书写一个装饰器,需要给get_age函数中的age进行校验
def check_age1(func):
    def inner1(n):
        # 增加新的功能:校验年龄
        if n < 0:
            n = -n
        # 调用原函数
        func(n)
    return inner1
f1 = check_age1(get_age)
f1(10)
f1(-10)

# 注意:如果原函数有参,在内部函数中增加新的功能,如果需要对原函数中的参数进行相应的运算
# 则可以给内部函数设置参数

# 2.装饰器的常见的形式
# 注意:装饰器本质是一个函数,对于装饰器或原函数,参数【默认参数,关键字参数,不定长参数】和返回值都可以正常使用
# a.
def test1():
    print("test~~~111")
def wrapper1(func):
    def inner1():
        print("new~~~1111")
        func()
    return inner1
f1 = wrapper1(test1)
f1()

print("*" * 50)

# b
def test1(n):
    print("test~~~222",n)
def wrapper1(func):
    def inner1(n):
        print("new~~~2222")
        func(n)
    return inner1
f1 = wrapper1(test1)
f1(10)

print("*" * 50)

# c
def test1(n):
    print("test~~~333",n)
    return 66
def wrapper1(func):
    def inner1(n):
        print("new~~~3333")
        r = func(n)
        print(r)
    return inner1
f1 = wrapper1(test1)
f1(10)

print("*" * 50)

# d
def test1(n):
    print("test~~~444",n)
    return 66
def wrapper1(func):
    def inner1(n):
        print("new~~~4444")
        r = func(n)
        print(r)
        return 'abc'
    return inner1
f1 = wrapper1(test1)
r1 = f1(10)
print(r1)

print("*" * 30)


# 3.@xxx
# 说明:@xxx,xxx表示装饰器的名称,实际是外部函数的函数名
# 语法:将@xxx应用在需要被装饰的函数的声明之前
# 注意:使用@xxx使用装饰器,必须先有装饰器,然后才能使用
def check_age2(func):
    print("外部函数")
    def inner2(n):
        print("内部函数~~~~")
        if n < 0:
            n = -n
        func(n)   # 调用原函数
    print("外部函数~~~~over")
    return inner2
@check_age2    # 相当于f1 = check_age2(get_age2),调用装饰器的外部函数
def get_age2(age):
    print(f"年龄:{age}")
get_age2(-18)    # 相当于f1(-18),调用装饰器的内部函数

"""
工作原理:
第一步:@check_age2
      a.func---->get_age2原
      b.get_age2---->inner2
第二步:get_age2(-18)
    a.调用inner2,然后执行到func(),才表示调用原函数  
"""

# 同一个装饰器同时装饰多个函数,相当于给多个函数同时增加同一个新的功能
# 注意:如果需要同一个装饰器装饰多个函数,为了满足不同函数的参数的需求,则装饰器的内部函数设置为不定长参数
def wrapper(func):
    def inner(*args,**kwargs):   # 打包
        # print(args,kwargs)
        # print(*args,**kwargs)
        func(*args,**kwargs)     # 拆包
        print("new!!!!!")
    return inner

@wrapper
def f1():
    print("111111")
@wrapper
def f2(a,b):
    print("22222",a,b)
@wrapper
def f3(num1,num2,num3,num4):
    print("3333")

f1()
f2(23,10)
f3(34,6,8,9)


# 【面试题】练习:书写一个装饰器,可以统计任意一个函数的执行时间
import  time
# 时间戳:获取当前时间距离1970.1.1 00:00:00的秒数
# print(time.time())
def get_time(func):
    def inner(*args,**kwargs):
        start = time.time()
        func(*args,**kwargs)
        end = time.time()
        return round(end - start,3)
    return inner

@get_time
def test():
    for i in range(100000):
        pass
r1 = test()
print(r1)

@get_time
def test1(n):
    for i in range(n):
        pass
r2 = test1(1000000)
print(r2)

2.进阶用法

#多个装饰器装饰同一个函数
# 作用:给同一个函数同时增加多个不同的功能
# a
def wrapper1(func1):
    def inner1(*args,**kwargs):
        print("第1个装饰器~~~~~start")
        func1(*args,**kwargs)
        print("第1个装饰器~~~~~end")
    return inner1
def wrapper2(func2):
    def inner2(*args,**kwargs):
        print("第2个装饰器~~~~~start")
        func2(*args,**kwargs)
        print("第2个装饰器~~~~~end")
    return inner2
def wrapper3(func3):
    def inner3(*args,**kwargs):
        print("第3个装饰器~~~~~start")
        func3(*args,**kwargs)
        print("第3个装饰器~~~~~end")
    return inner3

@wrapper1
@wrapper2
@wrapper3
def test():
    print("test~~~~~")
test()

"""
工作原理:
第一部分:调用外部函数
    @wrapper1
    @wrapper2
    @wrapper3
    def test():
        print("test~~~~~")
        
    a.调用wrapper3,func3---->test原,test---->inner3
    b.调用wrapper2, func2--->test【inner3】,test---->inner2
    c.调用wrapper1, func1--->test【inner2】,test---->inner1
    
第二部分:调用内部函数
    test()

    a.inner1--->func1【inner2】
    b.inner2--->func2【inner3】
    c.inner3--->func3【test原】
"""

二、函数递归

在实际开发中,递归使用较少,递归的工作效率没有循环高

"""
递归函数:如果一个函数,在函数体这种调用自身
使用递归需要注意的问题:
    a.需要找到一个临界值,可以让递归在某个合适的时机下停止下来
    b.函数相邻的两次调用之间存在某种规律
"""
# 1.恶意调用
# def a():
#     print('aaaa')
#     a()
# a()

# 2.递归的正确使用
# a.需求1:报一个数【位置】,获取在斐波那契数列中对应的数
"""
1   2   3   4   5   6   7   8   9   10   11.....
1   1   2   3   5   8  13   21  34  55   89
"""

"""
规律:
    a.第1个数和第2个数是固定的,都为1
    b.第n个数 = 第n-1个数  +  第n - 2个数
"""
def func(n):
    print(n)
    if n == 1 or n == 2:
        return 1
    else:
        return func(n - 1) + func(n - 2)

r = func(11)
print(r)


# b.需求:求1~某个数之间的整数和
"""
规律:
    a.如果n为1,结果直接为1
    b.如果n>=2,则结果为1~n-1之间的数的和 + n
"""
def fn(n):
    print(n)
    if n == 1:
        return 1
    else:
        return fn(n - 1) + n
r = fn(100)
print(r)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值