理解Python装饰器(Decorator)
date: 2017-04-14 00:06:46
Python的装饰器,顾名思义就是可以为已有的函数或对象起到装饰的作用,使得达到代码重用的目的。
从一个简单的例子出发
这个例子中我们已经拥有了若干个独立的函数。
#! python 2
# coding: utf-8
def a():
print("a")
def b():
print("b")
def c():
print("c")
a()
b()
c()
输出结果是
a
b
c
而我们想要给这三个函数都加上打印当前日期的功能,倘若没有学习装饰器,那我们可能要为每一个函数都添加一行语句。
#! python 2
# coding: utf-8
import time
def a():
print(time.asctime( time.localtime(time.time())))
print("a")
def b():
print(time.asctime( time.localtime(time.time())))
print("b")
def c():
print(time.asctime( time.localtime(time.time())))
print("c")
a()
b()
c()
这样看来需要添加的代码量似乎并不多,但如果需要被添加此功能的已经写好的模块已经有上百上千甚至上万?这样写岂不是过于繁杂,而有了装饰器,我们则可以像下面这样。
#! python3
# coding: utf-8
import time
# return time
def rtime(func):
def wrapper():
print(time.asctime( time.localtime(time.time())))
return func()
return wrapper
@rtime
def a():
print("a")
@rtime
def b():
print("b")
@rtime
def c():
print("c")
a()
b()
c()
怎么样,是不是简洁明了了很多。
更加通用一点的装饰器
可以看到,上面的三个函数都没有接受参数,那如果rtime去装饰含有参数的函数会怎样呢?
#! python3
# coding: utf-8
import time
# return time
def rtime(func):
def wrapper():
print(time.asctime(time.localtime(time.time())))
return func()
return wrapper
@rtime
def d(a):
print(a)
d(1)
显然,d函数包含了一个参数d,如果此时运行的话,则会出现报错
TypeError: wrapper() takes no arguments (1 given)
为了可以使得装饰器更加通用,我们可以像下面这样写:
#! python3
# coding: utf-8
import time
# return time
def rtime(func):
def wrapper(*args, **kwargs):
print(time.asctime(time.localtime(time.time())))
return func(*args, **kwargs)
return wrapper
@rtime
def d(a):
print(a)
d(1)
可以看到,其中添加了args和**kwargs,Python提供了可变参数args和关键字参数**kwargs用于处理未知数量参数,这样就能解决被修饰函数中带参数得问题。
那如果是装饰器本身想要带上参数呢,先记住这样一句话:本身需要支持参数得装饰器需要多一层的内嵌函数。下面看具体的代码实现:
#! python3
# coding: utf-8
import time
# return time
def rtime(x):
print(x)
def wrapper(func):
def inner_wrapper(*args, **kwargs):
print(time.asctime(time.localtime(time.time())))
return func(*args, **kwargs)
return inner_wrapper
return wrapper
@rtime(1) # x = 1
def d(a):
print(a)
d(2)
输出结果为
1
Wed Apr 12 20:43:54 2017
2
调用多个装饰器
python的装饰器支持多次调用,且调用的顺序与在被装饰函数前声明装饰器的顺序相反,如若想先调用装饰器demo1和demo2,则装饰时应先@demo2再@demo1。
类实现的装饰器
若想要通过类来实现装饰器,则需要修改类的构造函数__init__()并重载__call__()函数。下面是一个简单的例子:
#! python3
# coding: utf-8
import time
# return time
def rtime(x):
print(x)
def wrapper(func):
def inner_wrapper(*args, **kwargs):
print(time.asctime(time.localtime(time.time())))
return func(*args, **kwargs)
return inner_wrapper
return wrapper
# return time 不带参数的类实现
class rtime1(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(time.asctime(time.localtime(time.time())))
return self.func(*args, **kwargs)
# return time 带参数的类实现
class rtime2(object):
def __init__(self, x):
self.x = x
def __call__(self, func):
def wrapper(*args, **kwargs):
print(self.x)
print(time.asctime(time.localtime(time.time())))
return func(*args, **kwargs)
return wrapper
@rtime(1)
def d(a):
print(a)
@rtime1
def e(a):
print(a)
@rtime2(2)
def f(a):
print(a)
d(3)
e(4)
f(5)
输出结果为
1
Thu Apr 13 11:32:22 2017
3
Thu Apr 13 11:32:22 2017
4
2
Thu Apr 13 11:32:22 2017
5
Python内置装饰器
@property
内置装饰器property可以帮助我们为一个class写入属性
#! python3
# coding: utf-8
import time
class test(object):
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
temp = test()
temp.x = 1
print temp.x
输出结果为1,想必会有人疑惑为什么要这样写入属性,如果没有这样绑定属性直接将temp.x赋值的话,则属性x是不可控的,而通过property绑定属性之后,则可以在setter设定的时候添加对范围的判断,使得属性可控,property还有getter装饰器,不过getter装饰器和不带getter的属性装饰器效果一样。
@staticmethod & @classmethod
通过staticmethod和classmethod装饰器可以使得我们在不实例化类的情况下直接调用类中的方法:class_name.method()即可直接调用。
那么staticmethod和classmethod又有什么区别呢?
@staticmethod不需要表示实例的self和自身类的cls参数,也就是说可不传递参数。
@classmethod的第一个参数必须有且必须是表示自身类的cls参数。
理解Python装饰器(Decorator)的更多相关文章
- 如何理解Python装饰器
如何理解Python装饰器?很多学员对此都有疑问,那么上海尚学堂python培训这篇文章就给予答复. 一.预备知识 首先要理解装饰器,首先要先理解在 Python 中很重要的一个概念就是:“函数是 F ...
- python 装饰器(decorator)
装饰器(decorator) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 装饰器(decorator)是一种高级Python语 ...
- 理解 Python 装饰器看这一篇就够了
讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切. 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,让它 ...
- http://python.jobbole.com/85056/ 简单 12 步理解 Python 装饰器,https://www.cnblogs.com/deeper/p/7482958.html另一篇文章
好吧,我标题党了.作为 Python 教师,我发现理解装饰器是学生们从接触后就一直纠结的问题.那是因为装饰器确实难以理解!想弄明白装饰器,需要理解一些函数式编程概念,并且要对Python中函数定义和函 ...
- Python装饰器--decorator
装饰器 装饰器实质是一个函数,其作用就是在不改动其它函数代码的情况下,增加一些功能.如果我们需要打印函数调用前后日志,可以这么做 def log(func): print('%s is running ...
- Python 装饰器Decorator(一)
(一) 装饰器基础知识 什么是Python装饰器?Python里装饰器是一个可调用的对象(函数),其参数是另一个函数(被装饰的函数) 假如有一个名字为somedecorator的装饰器,target是 ...
- 理解Python装饰器
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权 ...
- 理解 python 装饰器
变量 name = 'world' x = 3 变量是代表某个值的名字 函数 def hello(name): return 'hello' + name hello('word) hello wor ...
- Python装饰器(Decorator)简介
Python有许多出色的语言特性,装饰器(Decorator)便是其中一朵奇葩.先来看看一段代码: def deco1(f): print 'decorate 1' return f def deco ...
随机推荐
- Maven+ajax+SSM实现查询
2.尚硅谷_SSM高级整合_使用ajax操作实现页面的查询功能 16.尚硅谷_SSM高级整合_查询_返回分页的json数据.avi 在上一章节的操作中我们是将PageInfo对象存储在request域 ...
- Lyft 宣布开源基础设施工具管理平台 Clutch!
今天我们很高兴地宣布,Lyft 的基础设施工具可扩展 UI 和 API 平台clutch已开放源代码,clutch使工程团队能够构建.运行和维护用户友好的工作流,这些工作流还包含特定于域的安全机制和访 ...
- 1.linux中的常用命令
本文积累工作中常用到的Linux命令 1. rz -be 文件上传到Linux服务器 此命令执行时,会弹出文件选择对话框,选择好需要上传的文件之后,点确定,就可以开始上传的过程了.上传的速度取决于当时 ...
- IntelliJ IDEA最新破解方法
IntelliJ IDEA最新破解方法 首先说下,本人使用idea版本是2021.2.3. 一.下载IDEA(推荐从官网下载) 官网地址:https://www.jetbrains.com/idea/ ...
- Python科学计算类库
Numpy是什么 Numpy是一个开源的Python科学计算库.使用Numpy,就可以很自然地使用数组和矩阵.Numpy包含很多实用的数学函数,涵盖线性代数运算.傅里叶变换和随机数生成等功能. 矩阵: ...
- 《剑指offer》面试题48. 最长不含重复字符的子字符串
问题描述 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串 ...
- Go环境配置和GoModule
Linux相关 Linux常用操作 mkdir directory --创建文件夹 vi file --创建文件,再关闭vim rm file --删除文件 rm -rf directory --递归 ...
- 微信小程序云开发框架
概述 一直做后端服务器开发,最近看了一篇文章介绍小程序的云开发模式,觉得挺有意思,就尝试了一下,由本文做个记录. 因为不是专业的小程序开发人员,也没有做过网页开发,所以论述中出现错误难以避免,请多谅解 ...
- 【记录一个问题】笔记本ThinkPad X1-Extreme安装ubuntu 18后,更新nvidia显卡驱动后出现显示问题,无法再登录
如题 更新的过程如下: sudo ubuntu-drivers autoinstall sudo reboot 后续准备在recovery模式中尝试删除驱动.
- 在DigitalOcean vps中安装vnstat监控流量,浏览器打开php代码。。。
由于DigitalOcean中没有发现可以观察已用流量的功能,有想知道自己的流量使用情况,所以安装了vnstat. 安装过程十分简单,见百度经验,官方主页等. 1.安装完vnstat后,直接命令vns ...