浅谈python中@装饰器 - 附例子(含类装饰器与函数装饰器)

浅谈python中@装饰器

提到@的使用首先要先讲一下装饰器的概念

关于装饰器(decorator)

先来看看官方文档上面是怎么写的:

A decorator is the name used for a software design pattern. Decorators
dynamically alter the functionality of a function, method, or class
without having to directly use subclasses or change the source code of
the function being decorated.
“装饰器是用于软件设计模式的名称。 装饰器可以动态更改功能,方法或类的功能,而不必直接使用子类或更改要修饰的功能的源代码。”(源自谷歌翻译)

而在python中装饰器是对python语法的特定更改,能更方便的修改函数和方法。通俗的说,装饰器相当于在不修改原有函数的基础上在其上增加别的功能。比如说我想每次使用函数的时候都打印一条日志作为标记,但是我又不想直接修改函数,这时装饰器就有用啦。装饰顾名思义是锦上添花的意思,在这个例子里“花”就是日志喽,大概是这样。

def triple_sum(a,b,c):
    print( "the sum is ",(a+b+c))
    
#log修饰器
def log_dec(func):
    def inner(a,b,c):
        print("logloglog")
        return func(a,b,c)
    return inner

new_fun=log_dec(triple_sum)
new_fun(1,2,3)

输出为
输出

这里还有个隐含的前置知识点,在python里,函数可以作为变量进行传递。

def triple_sum(a, b, c):
    print( "the sum is ",(a+b+c))

new_func = triple_sum
new_func(123, 234, 345)
print(new_func.__name__)

在这里插入图片描述

除了函数之外,类也可以作为装饰器进行包装

class Cube(object):
    def __init__(self, args):
        self.args = args

    def __call__(self, x, y):
        res = self.args(x, y)
        return res * res * res
# 这里Cube作为一个三次方的包装器,包装了一个普通的乘法函数
# 这里的乘法函数我用一个lambda表达式来略缩了
mul_nums = Cube(lambda x, y: x * y)
# 不使用lambda函数的话就是
#def mul_nums(x, y):
#    return x * y
#mul_nums = Cube(mul_nums)

print(mul_nums)
print(mul_nums(4, 3))

小总结

所以装饰器是什么,其实只是给当前的模块增加的新功能。装饰器可以是类,也可以是函数。它不会改变原来的函数本身,符合设计方法的开闭原则。

关于@(语法糖)

@ 实际上是python的语法糖,使用@对上面的两个例子进行改造
示例1:

def log_dec(func):
    print("logloglog")
    func(1,2,3)

@log_dec
def triple_sum(a,b,c):
    print( "the sum is ",(a+b+c))

结果输出为:
在这里插入图片描述
公式化一下@这个语法糖就是

@装饰器名 替代掉了 装饰器名(被装饰的函数)

即 triple_sum = log_dec(triple_sum)

示例2

@Cube
def mul_nums(x, y):
    return x * y

同理,@Cube替掉了mul_nums = Cube(mul_nums)

进阶

装饰器顺序

需要注意的是,想在已有函数上加的功能,需要在@之前声明(代码块的先后顺序)。同时,一个函数可以同时加几个装饰器。

从最下面的一个@函数开始运行,其下的函数作为他的输入。用print会看的更清楚一点

def log1(func):
    print("log1log1log1")

def log2(func):
    print("log2log2log2")
    func(1, 2, 3)

@log1
@log2
def triple_sum(a, b, c):
    print("the sum is ", (a + b + c))

输出为:
在这里插入图片描述
实际的运行相当于
triple_sum = log2(triple_sum)
triple_sum = log1(triple_sum)

装饰器 & 参数

1. 传参

可能有些盲生看到这里已经发现了华点,咋给triple_sum传参啊!(上面例子里面的值全都是写死的)这里我们就要对装饰器进行改造了。

在改造之前,需要知道一个前置知识,python中可以进行函数的嵌套,如

def func1():
    print("I'm in func1")
    def func2(msg):
        print("I'm in func2")
        print("I'm saying ",msg)
    func2("hello")

func1()

在这里插入图片描述
清楚了函数嵌套,再来看怎么改造装饰器参数

def log1(func):
    def wrapper(*args):
        print("logloglog")
        func(*args)
    return wrapper

@log1
def triple_sum(a, b, c):
    print("the sum is ", (a + b + c))

triple_sum(100,200,300)

在这里插入图片描述
使用函数嵌套就完成了装饰器的传参

2. 带参装饰器

此外,装饰器本身也可以携带参数。依然使用函数嵌套,再来一层。

def log_with_args(arg1,arg2):
    def log1(func):
        def wrapper(*args):
            print("logloglog")
            func(*args)
            print("arg1 is ",arg1,", args2 is ", arg2)
        return wrapper
    return log1

@log_with_args("hello","world")
def triple_sum(a, b, c):
    print("the sum is ", (a + b + c))

triple_sum(111,222,333)

在这里插入图片描述

End

以上即为装饰器的全部内容,欢迎评论区沟通指正。

参考

  1. 菜鸟教程 Python 函数装饰器
  2. 一大佬的文章,讲得很清楚
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值