Python中的装饰器

装饰器允许在函数或类中注入或修改代码。例如,假设你想在某个函数的开始和结束时执行某些操作,用装饰器就可以完成这样的任务。看一个例子你就会明白了。

In [18]: class myDecorator(object):
    ...: 
    ...:     def __init__(self, f):
    ...:         print "inside myDecorator.__init__()"
    ...:         f()
    ...: 
    ...:     def __call__(self):
    ...:         print "inside myDecorator.__call__()"
    ...: 
    ...: @myDecorator
    ...: def aFunction():
    ...:     print "inside aFunction()"
    ...:     

当编译器编译代码时,输出结果为

inside myDecorator.__init__()
inside aFunction()

这说明装饰器不需要我们自己调用,编译器会自动帮我们调用。看看经过装饰器装饰以后aFunction是什么模样?

In [19]: aFunction
Out[19]: <__main__.myDecorator at 0xf16b630>

可以看出此时的aFunction变成了myDecorator类的一个实例对象了,而不再是函数对象了,上述过程其实等价于:

In [23]: class myDecorator(object):
    ...: 
    ...:     def __init__(self, f):
    ...:         print "inside myDecorator.__init__()"
    ...:         f()
    ...: 
    ...:     def __call__(self):
    ...:         print "inside myDecorator.__call__()"
    ...: 
    ...: def aFunction():
    ...:     print "inside aFunction()"
    ...:     

In [24]: aFunction=myDecorator(aFunction)
inside myDecorator.__init__()
inside aFunction()

In [25]: aFunction
Out[25]: <__main__.myDecorator at 0xf16b1d0>

装饰器返回的对象要求它可以作为一个函数使用,这意味着它必须是可调用的。

因此,我们用作装饰器的任何类都必须实现特殊方法__call__。这样我们就可以像调用函数一样调用类的实例对象。

In [26]: aFunction()
inside myDecorator.__call__()

在来看另外一个例子:

In [27]: class entryExit(object):
    ...: 
    ...:     def __init__(self, f):
    ...:         self.f = f
    ...: 
    ...:     def __call__(self):
    ...:         print "Entering", self.f.__name__
    ...:         self.f()
    ...:         print "Exited", self.f.__name__
    ...: 
    ...: @entryExit
    ...: def func1():
    ...:     print "inside func1()"
    ...: 
    ...: @entryExit
    ...: def func2():
    ...:     print "inside func2()"
    ...: 
    ...: func1()
    ...: func2()
    ...: 
Entering func1
inside func1()
Exited func1
Entering func2
inside func2()
Exited func2

通过输出我们可以看到整个的执行流程:

类装饰器entryExit装饰函数func1和func2,装饰器返回的结果是两个类的实例对象,分别赋给func1和func2。此时的func1和func2不在指向函数对象,而是指向类的两个实例对象。

构造函数中保存的属性是作为参数传入的func1和func2函数。

执行fun1()和fun2(),调用__call__方法,__call__方法内部调用了作为参数传入的fun1和fun2函数

参考:https://www.artima.com/weblogs/viewpost.jsp?thread=240808

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值