python进阶-----第十七课 --装饰器

python进阶,在第一期的基础上做了极大的优化,整体更加美观易懂

十七、装饰器

如果是新手强烈建议代码拿去一步步调试,看是怎么运行的。

17.1、认识装饰器

定义:就是给已有函数增加额外功能,它本质就是一个闭包函数(闭包特点:
	a、函数嵌套  
	b、内部函数使用了外部函数的变量或参数  
	c、外部函数返回了内部函数)
功能特点: 
	a、不修改已有函数的源代码
    b、不修改已有函数的调用方式
    c、给已有函数增加额外的功能

装饰器的构成条件:闭包的基础上, 外部函数的参数有且只有一个并且是函数类型的闭包是装饰器

# 定义装饰器
# 加一个登陆成功的提示
def waibu(func):
    def neibu():
        func()
        print("登录成功")
    return neibu

# 装饰器的语法糖写法: @装饰器名字,完成对已有函数的装饰
@ waibu
def comment():
    print("请输入密码:")
    # print("登录成功")

comment()
# 结果:
>>> 请输入密码:
>>> 登录成功

写法2(不用语法糖)

def waibu(func):
    def neibu():
        func()  # func()函数其实是已有函数comment在调用
        print("登录成功")
    return neibu

# 装饰器的语法糖写法: @装饰器名字,完成对已有函数的装饰
# @ waibu
def comment():
    print("请输入密码:")
    # print("登录成功")

comment = waibu(comment)  # 使用@装饰或者是通过传参将两段函数相链接  waibu(comment) = neibu = new_func

# 不修改已有函数的调用方式
# new_func()
comment()    # comment()是neibu在调用
# 结果:
>>> 请输入密码:
>>> 登录成功

17.2、装饰器的使用

装饰器的使用场景: 定义一个装饰器统计函数执行的时间

import time  # 导入time模块
# print(time.time())  # 获取的是从1970年1月1日 0:0:0到现在的时间差
def waibu(func):
    def neibu():
        # 统计work函数的获取时间
        # 获取函数执行前的时间
        qian = time.time()
        func()   # function()是已有函数work()在调用
        # 获取函数执行后的时间
        hou = time.time()
        print(f"总计用时:{hou - qian}")
    return neibu


@ waibu     # 等价于外部函数  work = waibu(func)
def work():  # 打印0到9999
    for i in range(10000):
        print(i)

# work = waibu()
work()
# 结果:
>>> 0
>>> 1
>>> ......
>>> 4999
>>> 5000
>>> ......
>>> 9998
>>> 9999
>>> 总计用时:0.044999122619628906

17.3、装饰带参和通用装饰器

通用装饰器:装饰任意的函数

17.3.1、装饰带有参数的函数
def waibu(func):
    # 内部函数的类型和被装饰的的类型保持一致
    def neibu(a, b):
        print("正在执行加法")
        func(a, b)
    return neibu

# @ waibu
def add_num(num1 , num2):
    print(f"结果是:{num1 + num2}")

add_num = waibu(add_num)
add_num(3, 5)
# 结果:
>>> 正在执行加法
>>> 结果是:8
17.3.2、装饰带有参数和返回值的函数
def waibu(func):
    def neibu(a, b):
        # 内部函数的类型和被装饰函数的类型保持一致
        num = func(a, b)
        return num
    return neibu

# @ waibu
def add_num1(num1, num2):
    result = num1 + num2
    return result

add_num1 = waibu(add_num1)
print(add_num1(3, 5))
# 结果:
>>> 8
17.3.3、装饰带有不定长参数和返回值的函数
def waibu(func):
    def neibu(*a, **b):
        # 内部函数的类型和被装饰函数的类型保持一致
        num = func(*a, **b)
        return num
    return neibu


# @ waibu
def add_num1(*args, **kwargs):
    # *args:当传入的这个参数个数未知,且不需要知道参数名称时  *args:可以理解为长度不固定的列表。
    # **kwargs 当传入的参数个数未知,但需要知道参数的名称时(字典)**kwargs:可以理解为长度不固定的字典
    result = 0
    for i in args:
        result += i
    for i in kwargs.values():  # .values()提取值
        result += i
    return result

result = add_num1(1, 3, 6, 8)
result = add_num1(1, 3, 6, age=18)
print(result)
# 结果:
>>> 28
17.3.4、通用的装饰器
def dec(func):
    def inner(*a, **b):
        num = func(*a, **b)
        return num
    return inner

@ dec
def show():
    return "嘿嘿"

print(show())
# 结果:
>>> 嘿嘿

17.4、多个装饰器的使用

多个装饰器的使用: 多个装饰器装饰一个已有函数
需求:人生苦短,我学python,

人生苦短我学python

,再加

定义装饰器
def waibu_p(func):
    def neibu():
        u1 = "

"+func()+"

"
# dunc在调用conten return u1 return neibu def waibu_div(func): def neibu(): u1 = "
"+func()+"
"
# dunc在调用conten return u1 return neibu @ waibu_div @ waibu_p def conten(): return "人生苦短,我学python" print(conten()) # 结果: >>> <div><p>人生苦短,我学python</p></div> # 装饰过程,waibu_div(waibu_p(conten)),由内到外,先执行内部,再执行外部

带有参数的装饰器: 就是使用装饰器装饰函数的时候可以传入指定参数

def waibu(func):
    def neibu(c, d):
        func(c, d)
    return neibu

@waibu
def add_num(a, b):
    result = a + b
    print(result)
add_num(2, 5)

@waibu
def add_num(a, b):
    result = a - b
    print(result)

add_num(2, 5)
结果:
>>> 7
>>> -3
def a(flag):
    def waibu(func):
        def neibu(c, d):
            if flag == "+":
                print("正在执行加法计算...")
            elif flag == "-":
               print("正在执行减法计算...")
            func(c, d)
        return neibu
    return waibu

@a("+")
def add_num(a, b):
    result = a + b
    print(result)
add_num(2, 5)

@a("-")
def add_num(a, b):
    result = a - b
    print(result)

add_num(2, 5)
结果:
>>> 正在执行加法计算...
>>> 7
>>> 正在执行减法计算...
>>>-3


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

你可能感兴趣的:(#,python进阶,python)