前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入了解Python中的装饰器

深入了解Python中的装饰器

作者头像
tunsuy
发布2022-10-27 09:13:12
2620
发布2022-10-27 09:13:12
举报

一、 概述

Python的装饰器是AOP编程的一种实现,其他很多语言也都支持装饰器模式。 注:AOP是指面向切面编程,详见 AOP概念

一个装饰器允许你增加、修改或者完全修改一个方法或者函数的逻辑。使用装饰器,将与业务无关的逻辑移到装饰器中,这将会让你的代码更加的干净紧凑。

二、 装饰器举例

最经典的例子当然是Python内建的装饰器:@staticmethod@classmethod 。这些装饰器将一个类中的方法转换为静态方法(该方法的第一个参数不是 self),和类方法(该方法的第一个参数是 cls)。

如下所示:

代码语言:javascript
复制
class A(object):
    @classmethod
def foo(cls):
print cls.__name__
    @staticmethod
def bar():
print 'I have no use for the instance or class'
A.foo()
A.bar()

输出:

代码语言:javascript
复制
A
I have no use for the instance or class

三、 装饰器定义

装饰器就是一个接受一个可调用对象(被装饰的目标)的可调用对象,返回一个和源目标(被装饰对象)接受相同参数的可调用对象(装饰器)。

下面来解释下这段文字:

首先,什么是可调用对象呢?一个可调用对象在Python中就是包含一个叫 call() 方法的对象。具体来说就是可以是代码块、方法或者类。你也可以给你自己的类实现这个 call() 方法,这样你的类实例就变成了一个可调用对象,为了检测一个对象是否是可调用的,你可以在命令行中使用内建的 callable() 方法测试下:

代码语言:javascript
复制
callable(len)
True
callable('123')
False

注意:callable() 方法在Python3.0被移除了,但是在Python3.2又重新加入了。

四、 函数装饰器

一个函数装饰器是用来装饰一个函数或者方法的。假设我们想要在每个执行之前都先输出一个字符串”Yeah, it works!”。下面以非装饰器的方式来实现它。 原始方法:

代码语言:javascript
复制
def foo():
print 'foo() here'
foo()

输出:

代码语言:javascript
复制
foo() here

下面以一种很丑陋的方式来实现我们的需求

代码语言:javascript
复制
original_foo = foo
def decorated_foo():
print 'Yeah, it works!'
original_foo()
foo = decorated_foo
foo()

输出:

代码语言:javascript
复制
Yeah, it works!
foo() here

这种方式有几个问题:

  • 它会增加很多工作
  • 用中间名字污染了名字空间,如:original_foo()decorated_foo()
  • 你不得不对每一个你想要增加这个需求的方法增加同样的逻辑

然而用迭代器同样能够实现这样的需求,并且是可以重用的。如下所示:

代码语言:javascript
复制
def yeah_it_works(f):
def decorated(*args, **kwargs):
print 'Yeah, it works'
return f(*args, **kwargs)
return decorated

注:yeah_it_works() 是一个接受一个可调用对象f的函数。返回一个接受任何类型和数量的参数的可调用对象(嵌套函数 decorated) 现在我们可以在任何函数中重用它

代码语言:javascript
复制
@yeah_it_works
def f1()
print 'f1() here'
@yeah_it_works
def f2()
print 'f3() here'
@yeah_it_works
def f3()
print 'f3() here'
f1()
f2()
f3()

输出:

代码语言:javascript
复制
Yeah, it works
f1() here
Yeah, it works
f2() here
Yeah, it works
f3() here

五、 类装饰器

类装饰器是装饰整个类。它们在类定义时被替换。你能够对一个装饰器类增加或者减少方法,甚至将迭代器应用到所有的类的方法中。

假设我们要跟踪一个类抛出的所有异常,让我们假设已经有了一个函数装饰器叫 track_exceptions_decorator ,如果没有类装饰器,那么我们需要对每个方法应用这个函数装饰器或者采用 metaclasses。示例:

代码语言:javascript
复制
class A(object):
    @track_exceptions_decorator
def f1():
...
    @track_exceptions_decorator
def f2():
...
.
.
.
    @track_exceptions_decorator
def f100():
...

一个类装饰器可以达到相同的效果:

代码语言:javascript
复制
def track_exception(cls):
# Get all callable attributes of the class
callable_attributes = {k:v for k, v in cls.__dict__.items() if callable(v)}
# Decorate each callable attribute of to the input class
for name, func in callable_attributes.items():
decorated = track_exceptions_decorator(func)
setattr(cls, name, decorated)
return cls
@track_exceptions
class A:
def f1(self):
print('1')
def f2(self):
print('2')
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有文化的技术人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、 概述
  • 二、 装饰器举例
  • 三、 装饰器定义
  • 四、 函数装饰器
  • 五、 类装饰器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档