Python基础32:装饰器--无参、有参装饰器

# **************************************************************************
# Python学习
# **************************************************************************
# ** 所属主题: 函数
# ** 所属分层: 32 装饰器
# ** 功能描述: 32 装饰器
# ** 创 建 者: 陈红伟
# ** 创建日期: 2021/3/27 10:44 下午
# **************************************************************************
# ** 修改日期     修改人    修改内容
# ** 2021/3/28   陈红伟    新增学习内容代码
# **************************************************************************

# 装饰器:
"""
1、什么是装饰器:
    器指的是工具,可以定义成函数
    装饰指的是为其他事物添加额外的东西点缀

    合到一起的解释:
        装饰器指的是定义一个函数,该函数是用来为其他函数的添加额外的功能(闭包函数)

2、为什么要用装饰器:
    开放封闭原则
        开放:指的是对拓展功能是开放的
        封闭:指的是对修改源代码是封闭的

    装饰器就是在不修改被装饰器对象源代码以及调用方式的前提下为被装饰对象添加新功能

3、怎样使用装饰器:


"""

###################################################################
# 无参装饰器  示例:@wrapper
###################################################################


# 需求:在不修改index函数的源代码以及调用方式的前提下为其添加统计运行时间的功能
def index(x,y):
    time.sleep(2)
    print('index %s %s' %(x,y))


# 解决方案一:虽然效果实现了,但是不符合需求,因为修改了源代码
import  time
def index(x,y):
    start = time.time()
    time.sleep(2)
    print('index %s %s' %(x,y))
    stop = time.time()
    print(stop-start)
index(111,222)
# index 111 222
# 2.0040969848632812


# 解决方案二:
import  time
def index(x,y):
    time.sleep(2)
    print('index %s %s' %(x,y))

def haoshi(x,y):
    start = time.time()
    index(x,y)
    stop = time.time()
    return (stop-start)

print(haoshi(111,222))
# index 111 222
# 2.0044641494750977


# 解决方案三:利用装饰器解决
import  time
def index(x,y):
    time.sleep(2)
    print('index %s %s' %(x,y))

# 装饰器
def wrapper(func):
    def haoshi(*args,**kwargs):
        start = time.time()
        func(*args,**kwargs)
        stop = time.time()
        return (stop-start)
    return haoshi

# 偷梁换柱
f = wrapper(index) # 还可以使用一种方式实现同样的逻辑: 在被装饰对象(函数)的正上方写上 "@+装饰器名字",但是装饰器名字要先定义好,再使用; 例如:在index()函数上面写上@wrapper
print(f(111,222))
# index 111 222
# 2.000530958175659

# 语法糖  在被装饰对象(函数)的正上方写上 "@+装饰器名字",但是装饰器名字要先定义好,再使用; 例如:在index()函数上面写上@wrapper
@wrapper
def index(x,y):
    time.sleep(2)
    print('index %s %s' %(x,y))

print(index(3333,3333))
# index 3333 3333
# 2.0049400329589844




# 总结:
def outer(func):
    def wrapper(*args,**kwargs):
        # 1、调用原函数
        # 2、为其增加新功能
        print('wrapper ....')
        res = func(*args,**kwargs)
        return res
    return wrapper


@outer  # 等价于 func_add = outer(func_add)
def func_add(a,b):
    return a+b

print(func_add(1,1))
# wrapper ....
# 2


def func_add(a,b):
    return a+b
# 去掉装饰器后
print(func_add(1,1)) # 2 只是按源函数执行,并没有用到装饰器装饰(此处指的是没有打印出wrapper ...)
print(func_add) # <function func_add at 0x7fdaa24059d0> 去掉装饰器之后,可以看到func_add的内存地址指向的是func_add

@outer  # 等价于 func_add = outer(func_add)
def func_add(a,b):
    return a+b

# 但是,还是有个缺点,并不是完全一致
print(func_add)  # <function outer.<locals>.wrapper at 0x7ffb75d058b0>  可以看到func_add的内存地址指向的是wrapper

# 如果想变成和原函数的属性信息(name、doc 等等)一样,(实现真正的偷梁换柱),需要引入包。wraps
from functools import wraps

def outer(func):
    def wrapper(*args,**kwargs):
        # 1、调用原函数
        # 2、为其增加新功能
        print('wrapper ....')
        res = func(*args,**kwargs)
        return res
    return wrapper

print(func_add.__name__) # wrapper  因为被封装了

def outer(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        # 1、调用原函数
        # 2、为其增加新功能
        print('wrapper ....')
        res = func(*args,**kwargs)
        return res
    return wrapper

print(func_add.__name__) # wrapper  这里还有疑问??????????????????


###################################################################
# 有参装饰器  示例:@wrapper("hello")
###################################################################
# 一、知识储备
# 由于语法糖@的限制,outter函数只能有一个参数,并且只用来接受被装饰对象的内存地址;
# 所以wrapper参数不能动,outter参数也不能动,那我需要其他的参数怎么办呢?

def outter(func):
    def wrapper(*args,**kwargs):
        res = func(*args,**kwargs)
        return res
    return wrapper

@outter
def index(x,y):
    print(x,y)


# 需求,我要在原来的func的基础上加上验证的功能:





def youcan_func(check):
    def outter(func):
        def wrapper(*args, **kwargs):
            flag = False
            if check == 'file':
                flag = True
            if check == 'oldp':
                flag = True
            if check == 'mysql':
                flag = True
            if flag:
                print(args,kwargs)
                res = func(*args, **kwargs)
            else:
                res = None
            return res
        return wrapper
    return outter


def func(x,y):
    return x+y

# 语法糖
@youcan_func(check='file')  # 相当于 调用了函数youcan_func(check='file') 变成了@outter ;
                            # 然后@outter就是无参装饰器的语法糖了(相当于using_file=outter(using_file)的内存地址)
                            # 然后调用using_file 其实就是调用wrapper
def using_file(x,y):
    print('using file check')
    return x*y

@youcan_func(check='oldp')
def using_oldp(x,y):
    print('using oldp check')

@youcan_func(check='mysql')
def using_mysql(x,y):
    print('using mysql check')



print(using_file(1,1))
# (1, 1) {}
# using file check
# 1   # 特别注意⚠️: 这里是1 不是2  因为执行的是1*1  不是 1+1
# using_oldp(2,2)
# using_mysql(3,3)


# 总结:
def 原来的函数(x,y):
    return x+y

# 无参装饰器模版:
def 无参装饰器(原来的函数):
    def wapper(*args,**kwargs):
        res = 原来的函数(*args,**kwargs)
        return res
    return wapper

# 有参装饰器模版:
def 有参装饰器(q,w):
    def 无参装饰器(原来的函数):
        def wapper(*args,**kwargs):
            if(q==1 and w==1):
                res = 原来的函数(*args,**kwargs)
            else:
                pass
            return res
        return wapper
    return 无参装饰器

# 怎么用?
# 在原来的函数上方写上@无参装饰器(q=1,w=1)
# 例如:
@无参装饰器
def 原来的函数1(x,y):
    return x+y

# 调用:
print(原来的函数1(1,2))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值