1、装饰器的理解

装饰器是将一个函数镶嵌在另一个函数中进行重复使用的目的,不改变其结构,增加函数的使用方式,但是不用写过多冗余的代码;

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
通常用到的功能:1.引入日志;2.函数执行时间统计;3.执行函数前预备处理;4.执行函数后清理功能;5.权限校验;6.缓存

2、实现原理与通用写法

咱们可以从一个简单的记录函数运行时间的简单装饰器,举一反三,推导出一个通用的装饰器写法

import timedef timer(func):'''记录方法运行时间的装饰器:param func: 方法:return:函数对象'''def deco(*args, **kwargs):startTime = time.time()f = func(*args, **kwargs)endTime = time.time()msecs = (endTime - startTime) * 1000print("time is %d ms" % msecs)return f # 如果 func 有返回值得话,需要在此return回去,否则,默认返回值为 None,一般默认都返回return deco@timer
def test(parameter):print("test is running!")time.sleep(1)return "Returned value" # 该函数有返回值,所以需要在 装饰器中的 deco 方法中 写返回值t = test('aa')
print(t)

这是一个很简单的通用的记录时间的装饰器,从而推导出一个通用的装饰器写法:

def func_name(func): # 自定义装饰器函数名def deco(*args, **kwargs): # 将所有参数原封不动的进行传递print("在这个分割线之上写函数运行前的操作")
#         -----------分割线-----------f = func(*args, **kwargs)
#         -----------分割线-----------print("在这个分割线之后,return之前,写函数运行后的操作")return f # 如果 func 有返回值得话,需要在此return回去,否则,默认返回值为 None,一般默认都返回return deco@func_name
def test(parameter):  # 8print("test is running!")time.sleep(1)return "Returned value" # 该函数有返回值,所以需要在 装饰器中的 deco 方法中 写返回值t = test('aa')
print(t)

ok 装饰器到此可以完事了,一般情况下都能满足需求了,网上看那么多原理,有点儿浪费时间,我偏向实操型,实在不喜欢啰嗦那么多,就是干。

当然在开发过程中, 我们可能会遇到一些特殊情况,比如参数问题
1、给装饰器函数代参数(通用)
2、将执行函数的参数拆分计算等(比如:1000w的数据,拆分成100份执行等)(定制)
那就按顺序来
1、写一个代参数的装饰器

def logging(level):def wrapper(func):def inner_wrapper(*args, **kwargs):print("[{level}]: enter function {func}()".format(level=level, func=func.__name__))return func(*args, **kwargs)return inner_wrapperreturn wrapper@logging(level='INFO')
def say(something):print("say {}!".format(something))# 如果没有使用@语法,等同于
# say = logging(level='INFO')(say)@logging(level='DEBUG')
def do(something):print("do {}...".format(something))if __name__ == '__main__':say('hello')do("my work")

发现:就是在上面的通用的模板上又套了一层!!!,然后拿到里面的参数即可! so easy!!!

2、写一个参数拆分的装饰器,这个就稍微有点定制型了,不能像上面的一样通用了,举个 栗子:

def func_name(func): # 自定义装饰器函数名def deco(*args, **kwargs): # 将所有参数原封不动的进行传递print(args[0])f_list = []for i in range(0,args[0],100000):print(i)f_list.append(func(i))
#         f_list # 这儿应该按照既定规则,继续对这个结果进行拼接,如果是写文件、入库等操作,可以不用returnreturn f_list   # 这儿如果有返回值得话,应该是return deco@func_name
def test(parameter):  # 8print("test is running!")time.sleep(1)return "Returned value" # 该函数有返回值,所以需要在 装饰器中的 deco 方法中 写返回值t = test(1000000)
print(t)

可以看出来,这个的定制性稍微高点,不通用,但是我们实现了我们的需求,所以,我们最应该理解并学会的是怎么用!!!

-------------------下面介绍一下:基于类实现的装饰器和内置装饰器,如果你需要就继续看吧-------------------

# 可以看出来,这个的定制性稍微高点,不通用,但是我们实现了我们的需求,所以,我们最应该理解并学会的是怎么用!!!

# 下面在介绍一下基于类实现的装饰器,那问题来了,我是实战派,我并没有用类装饰器的需求,所以,当个大盗吧,以后用到了不至于瞎找了!!!

# 装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。
# 只要某个对象重载了__call__()方法,那么这个对象就是callable的。

class Test():def __call__(self):print 'call me!'t = Test()
t()  # call me

# 像__call__这样前后都带下划线的方法在Python中被称为内置方法,有时候也被称为魔法方法。重载这些魔法方法一般会改变对象的内部行为。
# 上面这个例子就让一个类对象拥有了被调用的行为。

# 回到装饰器上的概念上来,装饰器要求接受一个callable对象,并返回一个callable对象(不太严谨,详见后文)。
# 那么用类来实现也是也可以的。我们可以让类的构造函数__init__()接受一个函数,然后重载__call__()并返回一个函数,也可以达到装饰器函数的效果。

class logging(object):def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):print "[DEBUG]: enter function {func}()".format(func=self.func.__name__)return self.func(*args, **kwargs)
@logging
def say(something):print "say {}!".format(something)

# 带参数的类装饰器#
# 如果需要通过类形式实现带参数的装饰器,那么会比前面的例子稍微复杂一点。那么在构造函数里接受的就不是一个函数,而是传入的参数。通过类把这些参数保存起来。
# 然后在重载__call__方法是就需要接受一个函数并返回一个函数。

class logging(object):def __init__(self, level='INFO'):self.level = leveldef __call__(self, func): # 接受函数def wrapper(*args, **kwargs):print "[{level}]: enter function {func}()".format(level=self.level,func=func.__name__)func(*args, **kwargs)return wrapper  #返回函数@logging(level='INFO')
def say(something):print "say {}!".format(something)

# 还有 内置的装饰器 ?!? 啥时候能用到啊。。。

# 内置的装饰器和普通的装饰器原理是一样的,只不过返回的不是函数,而是类对象,所以更难理解一些。

# @property
# 在了解这个装饰器前,你需要知道在不使用装饰器怎么写一个属性。

def getx(self):return self._xdef setx(self, value):self._x = valuedef delx(self):del self._x# create a property
x = property(getx, setx, delx, "I am doc for x property")

# 以上就是一个Python属性的标准写法,其实和Java挺像的,但是太罗嗦。有了@语法糖,能达到一样的效果但看起来更简单。

@property
def x(self): ...

# 等同于

def x(self): ...
x = property(x)

# 属性有三个装饰器:setter, getter, deleter ,都是在property()的基础上做了一些封装,因为setter和deleter是property()的第二和第三个参数,不能直接套用@语法。
# getter装饰器和不带getter的属性装饰器效果是一样的,估计只是为了凑数,本身没有任何存在的意义。经过@property装饰过的函数返回的不再是一个函数,而是一个property对象。

>>> property()
<property object at 0x10ff07940>

# @staticmethod,@classmethod#
# 有了@property装饰器的了解,这两个装饰器的原理是差不多的。@staticmethod返回的是一个staticmethod类对象,而@classmethod返回的是一个classmethod类对象。
# 他们都是调用的是各自的__init__()构造函数。

class classmethod(object):"""classmethod(function) -> method"""    def __init__(self, function): # for @classmethod decoratorpass# ...
class staticmethod(object):"""staticmethod(function) -> method"""def __init__(self, function): # for @staticmethod decoratorpass# ...
# 装饰器的@语法就等同调用了这两个类的构造函数。class Foo(object):@staticmethoddef bar():pass# 等同于 bar = staticmethod(bar)

# 至此,我们上文提到的装饰器接口定义可以更加明确一些,装饰器必须接受一个callable对象,其实它并不关心你返回什么,可以是另外一个callable对象(大部分情况),
# 也可以是其他类对象,比如property。

python中的装饰器的使用实战相关推荐

  1. python装饰器原理-python 中的装饰器及其原理

    装饰器模式 此前的文章中我们介绍过装饰器模式: 装饰器模式中具体的 Decorator 实现类通过将对组建的请求转发给被装饰的对象,并在转发前后执行一些额外的动作来修改原有的部分行为,实现增强 Com ...

  2. python类装饰器详解-python 中的装饰器详解

    装饰器 闭包 闭包简单的来说就是一个函数,在该函数内部再定义一个函数,并且这个内部函数用到了外部变量(即是外部函数的参数),最终这个函数返回内部函数的引用,这就是闭包. def decorator(p ...

  3. python中的装饰器decorator

    python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x):return ...

  4. python编写装饰器_写python中的装饰器

    python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) 1 de ...

  5. python中的装饰器(基础装饰器)

    文章目录 一 前置知识-高阶函数,闭包 1. 高阶函数 2. 闭包 二 函数装饰器 1. 什么是装饰器(原理)? 2. 装饰器的实现 3. 何时执行装饰器 4. wraps方法 三 类装饰器 一 前置 ...

  6. [转载]理解PYTHON中的装饰器

    [翻译]理解PYTHON中的装饰器 来源stackoverflow上的问题 链接 python的函数是对象 要理解装饰器,首先,你必须明白,在python中,函数是对象. 这很重要. 简单例子来理解为 ...

  7. 为什么说想到Python中的装饰器是天才

    为什么说想到Python中的装饰器是天才 只需一个@符号就能分析.测试和重复使用你的代码 带着魔杖的仙女在Python代码中飞舞 软件中有没有什么是神奇的小魔法? 有,装饰器却非常接近! 如果说有一件 ...

  8. python中的装饰器有哪些-python 装饰器以及开发中常用的例子

    有时候我们想为多个函数,同意添加某一种功能,比如及时统计,记录日志,缓存运算结果等等,而又不想改变函数代码 那就定义装饰器函数,用它来生成一个在原函数基础添加了新功能的函数,代替原函数 参考金角大王的 ...

  9. python中的装饰器怎么运行_Python 装饰器入门(上)

    翻译前想说的话: 这是一篇介绍python装饰器的文章,对比之前看到的类似介绍装饰器的文章,个人认为无人可出其右,文章由浅到深,由函数介绍到装饰器的高级应用,每个介绍必有例子说明.文章太长,看完原文后 ...

最新文章

  1. spring bean 创建失败的常见原因
  2. 最终一致性,一致只会迟到,但绝不会缺席
  3. im4java转换图片格式_ImageMagick和im4java处理图片[转]
  4. 《C和指针》读书笔记 第5章-操作符和表达式
  5. 【web项目】—the type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from ....
  6. Gentoo 安装日记 04 (开启ssh服务,ssh登录虚拟机)
  7. vba上传文件到ftp服务器指定目录下面
  8. shell脚本相关指令
  9. python都有哪些变量_Python变量作用域有哪些
  10. Swagger Annotation 详解(建议收藏)
  11. Docker 为什么输给了Kubernetes?Docker 员工自述!
  12. JAVA共享图片管理系统毕业设计 开题报告.
  13. 华硕h410csm怎么开启_华硕主板怎么开启uefi模式?华硕主板BIOS开启uefi模式详细方法...
  14. 基于微信小程序的毕业设计题目(19)php菜谱美食小程序(含开题报告、任务书、中期报告、答辩PPT、论文模板)
  15. 24、将Div中的所有元素保存为图片 Html2Canvas
  16. 217小白最新详细linux环境下安装博客WordPress教程
  17. python利用tushare下载数据并计算当日收益率
  18. uniapp 手写canvas海报(兼容android/ios/h5/微信小程序)
  19. 福大软工1816 · 第五次作业 - 结对作业2
  20. 阿里云高级技术专家白常明:边缘云的技术挑战和应用创新

热门文章

  1. cocos stuido的ccs文件加载成功 缺不显示图片的问题
  2. 2.前端面试 css篇
  3. 2.1 jmeter及其插件的安装
  4. mysql实战45讲(23-26)
  5. ucos-ii嵌入式操作系统任务调度(二)----任务切换瞬间cpu做了什么以及任务任务切换函数OS_TASK_SW
  6. Qt:emit是个什么?
  7. mysql collect_set_Hive sql 使用group by 字段被限制使用 collect_set/collect_list处理
  8. android 6.0 单手模式,小米4单手操作怎么用 MIUI 6单手模式设置
  9. Vue2.x全家桶学习笔记
  10. Aspose.Total for C++是一个完整的C++文件格式自动化库包