【Python】函数装饰器、类装饰器的实现

什么是装饰器

装饰器本身是一个函数 ,作用是为现有存在的函数,在不改变函数的基础上去增加一些功能进行装饰,装饰器是通过闭包的形式实现的。
我另一篇博客:☞闭包的实现原理,如何在内部函数修改外部函数的变量

函数万能装饰器

这个装饰器只是一种形式,没有实际意义。

# 定义万能函数装饰器
def outFunc(func):
    # 接收不同的参数
    def wrapper(*args, **kwargs):
        print('万能装饰器')
        # 再原样传回给被装饰的函数
        return func(*args, **kwargs)

    return wrapper

# 进行装饰
@outFunc
def addNmu(a,b):

    return a+b
# 调用被装饰的addNum函数
print(addNmu(3,4))

# 执行效果
# 万能装饰器
# 7

类装饰器

实现方法:在类中通过使用 __init__和 __call__方法来实现,__init__接收要被装饰的函数,__call__实现具体的装饰内容。
类装饰器也是用来装饰函数的。
一切都在代码中:

class Test(object):
    # 通过初始化方法,将要被装饰的函数传进来并记录下来
    def __init__(self, func):
        self.__func = func

    # 重写 __call__ 方法来实现具体装饰内容
    def __call__(self, *args, **kwargs):
        print('类的装饰器实现')
        self.__func(*args, **kwargs)

def show():
    print('i am func show')
    
# 装饰前,show是一个函数
show()

# 装饰后,show变成了Test类的实例对象
test1 = Test(show)
test1()
#------------------------------------------------------
# 执行效果
# 装饰前
# i am func show
# 装饰后
# 类的装饰器实现
# i am func show

有没有注意到__call__方法

__call__方法:Python中,只要在创建类的时候定义了__call__方法,这个类就是可调用的。
什么意思呢?通过几段代码来看:

class Call(object):
    n = 1

# 实例化对象    
test2 = Call()
print(test2.n)

# 结果
# 1

思考,我们能不能像调用函数一样使用类对象呢?

class Call(object):
    n = 1
    
test2 = Call()
print(test2())

运行结果:
在这里插入图片描述
错误提示,Call不能被调用;加入call方法:

class Call(object):

    def __call__(self, *args, **kwargs):
        n = 1
        return n
    
test2 = Call()
print(test2())

# 运行结果
# 1
结论

是不是感觉有点多此一举?我们在这里是为了理解__call__方法的作用:

  • Python中的所有东西都是对象,其中包括Int/str/func/class这四类,它们都是对象,都是从一个类创建而来的。
  • 为了将一个类实例当做函数调用,我们需要在类中实现__call__()方法。
  • 最重要的一点,前面类装饰器的实现就是借助__call__方法实现的。

补充

__new__方法:实例化对象(开辟内存空间)
__init__方法:对实例化对象进行初始化操作
__call__方法:让类可调用,实现装饰器
__str__方法:当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__方法,那么就会打印从在这个方法中return的数据
__del__方法:当删除对象时,python解释器会默认调用这个方法,让这个对象的引用计数减1,当对象的引用计数为0的时候,则对象才会被真正删除(内存被回收)。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值