理解python中的装饰器

python的函数是对象

要理解装饰器,首先,你必须明白,在python中,函数是对象. 这很重要.

简单例子来理解为什么

好了,记住这点,我们将会很快用到它.

Python函数另一个有趣的特性是,函数可以被定义在另一个函数里面

函数引用

好了,到这里了,接下来是有意思的部分,我们刚才看到 函数是对象,然后:

1.函数可以赋值给一个变量

2.函数可以定义在另一个函数内部

即,这也意味着一个函数可以返回另一个函数:-),让我们来看另一段代码

但是稍等,如果你可以返回一个函数,那么你也可以将函数作为参数传递

好了,现在你已经了解要理解装饰器的每件事.

装饰器就是封装器,可以让你在被装饰函数之前或之后执行代码,而不必修改函数本身

手工装饰器

如何书写一个装饰器

到这里,或许你想每次调用a_stand_alone_function都使用a_stand_alone_function_decorated替代之
很简单,只需要将a_stand_alone_function用my_shiny_new_decorator装饰返回

装饰器阐述

前面的例子,使用装饰器语法

是的,就是这么简单. @decorator是下面代码的简写

装饰器只是 装饰器模式的python实现

python代码中还存在其他几个经典的设计模式,以方便开发,例如迭代器iterators

当然,你可以累加装饰器

使用python装饰器语法

装饰器位置的顺序很重要

最后回答问题

好了,到这里你可以高兴地离开了,或者来看下一些装饰器高级的用法

向装饰器函数传递参数

装饰方法

Python中对象的方法和函数是一样的,除了对象的方法首个参数是指向当前对象的引用(self)。这意味着你可以用同样的方法构建一个装饰器,只是必须考虑self

当然,你可以构造一个更加通用的装饰器,可以作用在任何函数或对象方法上,而不必关系其参数
使用

如下代码

向装饰器传递参数

好了,现在你或许会想是否可以向装饰器本身传递参数

装饰器必须使用函数作为参数,所以这看起来会有些复杂,你不能直接传递参数给装饰器本身

在开始处理这个问题前,看一点提醒

上面两个形式本质上是相同的, “my_decorator” 被调用.所以当你使用”@my_decorator”,告诉python一个函数被变量”my_decorator”标记
这十分重要,因为你提供的标签直接指向装饰器…或者不是,继续

我们跳过中间变量,做同样的事情

使用装饰器语法,更简短

到这里,我们使用@调用一个函数

回到问题,向装饰器本身传递参数,如果我们可以通过函数去创建装饰器,那么我们可以传递参数给这个函数,对么?

好了,that’s it.参数可以设置为变量

你可以看到,你可以使用像其它函数一样使用这个方法向装饰器传递参数.如果你愿意你甚至可以使用 arg *kwargs.

但是记住,装饰器仅在Python代码导入时被调用一次,之后你不能动态地改变参数.当你使用”import x”,函数已经被装饰,所以你不能改变什么

练习:一个装饰装饰器的装饰器

作为奖励,我将展示创建可以处理任何参数的装饰器代码片段. 毕竟,为了接收参数,必须使用另一个函数来创建装饰器

让我们来给装饰器写一个装饰器:

使用:

我知道,到现在你一定会有这种感觉,就像你听一个人说“在理解递归之前,你必须首先了解递归”,但是现在,掌握这儿你有没有觉得很棒?

装饰器使用最佳实践

  • 这是Python2.4的新特性,所以确保你的代码在2.4及之上的版本运行
  • 装饰器降低了函数调用的性能,记住这点
  • You can not un-decorate a function. There are hacks to create decorators that can be removed but nobody uses them. So once a function is decorated, it’s done. For all the code.
  • 装饰器包装函数,所以很难debug

Python2.5解决了最后一个问题,它提供functools模块,包含functools.wraps.这个函数会将被装饰函数的名称,模块,文档字符串拷贝给封装函数,有趣的是,functools.wraps是一个装饰器:-)

装饰器为何那么有用

现在的问题是,我们用装饰器来坐什么?看起来很酷很强大,但是如果有实践的例子会更好.好了,有1000种可能。经典的用法是,在函数的外部,扩展一个函数的行为(你不需要改变这个函数),或者,为了调试的目的(我们不修改的原因是这是临时的),你可以使用装饰器扩展一些函数,而不用在这些函数中书写相同的函数实现一样的功能

DRY原则,例子:

装饰器意味着,你可以用正确的方法实现几乎所有的事情,而不必重写他们

Python本身提供了一些装饰器:property,staticmethod,等等,

Django使用装饰器去管理缓存和权限. Twisted to fake inlining asynchronous functions calls.用途广泛

EDIT: 鉴于这个回答的完美,人们希望我去回答metaclass,我这样做了

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

1 5 收藏 评论

关于作者:wklken

Pythonista/vimer 个人主页 · 我的文章 · 37 ·   

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部