22.Python进阶_类实现装饰器04

咱们知道函数是可以当作装饰器, 他应用的是 闭包函数特性, 实际类只要符合闭包的特性也可以当作装饰器。
实现装饰器两种方式:

  • 函数实现:使用闭包;
  • 类实现;

学习之前先看一下__call__魔法方法:

class Person():
    def __init__(self,name):
        self.name=name

p=Person('小静')
p()  #直接调用实例对象

为了符合装饰器特征,直接调用实例对象会报错:

Traceback (most recent call last):
  File "C:/workspace/pythonTest/pythonDemo/call.py", line 6, in <module>
    p()  #
TypeError: 'Person' object is not callable

报错结果是说Person对象不是可调用对象(callable),python中一切皆对象,函数也是对象,
关于可调用对象,我们平时自定义的函数、内置函数和类都属于可调用对象,但凡是可以把一对括号()应用到某个对象身上都可称之为可调用对象,判断对象是否为可调用对象可以用函数 callable

就是说__call__()方法能够让类的实例对象,像函数一样被调用

看一下__call__的实现:

一个特殊的魔术方法可以让类的实例的行为表现的像函数一样,你可以调用他们,将一个函数当做一个参数传到另外一个函数中等等。这是一个非常强大的特性让Python编程更加舒适甜美。 __call__(self, [args...])
允许一个类的实例像函数一样被调用。实质上说,这意味着 x() 与 x.call() 是相同的。注意 call 参数可变。这意味着你可以定义 __call__ 为其他你想要的函数,无论有多少个参数。
__call__ 在那些类的实例经常改变状态的时候会非常有效。相当于重载括号运算符;

再加入__call_方法后看一下:

class Person():
    def __init__(self,name):
        self.name=name
    def __call__(self):
        print(self.name)

p=Person('小静')
p()  #直接调用实例对象

此时执行结果正确;

再看一个例子分析一下:

class Person():
    def __init__(self,func):
        print(" init 方法进行初始化fun")
        self.__func=func
    def __call__(self):
        print("开始调用实例方法 fun")
        self.__func()


@Person
def fun():
    print("fun 方法执行")

fun()

执行结果如下:
init 方法进行初始化
开始执行 实例方法 fun
fun 方法执行

分析过程:

  1. @Person 相当于 fun=Person(fun) ;
  2. Person(fun)相当于实例化, 只是他传递的比较特殊是个方法的引用,
  3. 首先走的是 init 方法 初始化 , 打印了 init 方法进行初始化 ,
  4. 然后把方法fun 的引用交给了私有属性 __func
  5. 实例化完成以后 把Person(fun) 实例化对象把指针传递给 fun, fun指向实例化对象
  6. 当执行 fun() 的时候,就相当于 前面我们介绍的第一部分的内容,实例化方法自动调用了 call 执行call方法里的 self.__func() ,
  7. 这个 func的指针指向大家了解吗, fun的指针 传递给>func指针又给了>__func, 所以当我们执行self.__func 的时候 就相当于 执行 fun() 也就是被装饰的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值