装饰器这个名词一听就充满了高级感,而且很多情况下确实也不常用。但装饰器有装饰器的好处,至少了解这个对装逼还是颇有益处的。网上有很多关于装饰器的解说,但通常都太过“循序渐进”,有的还会讲一些“闭包”之类的概念,像我这种脑子不太好使的经常就是前读后忘……所以我想自己来写一个非常通俗易懂的解说。

个人最早真正接触装饰器是在Kaggle上看别人使用numba加速,函数前一行短短的 @jit 让你的代码快到飞起,看起来也很简洁。那究竟装饰器是什么,它又能干嘛呢?

P1 装饰器的作用

装饰器的作用是对多种函数执行一个通用操作。重点是多种和通用。举个栗子来说,我写了一个计算执行时长的装饰器,那么我可以把它安在函数A上,也可以把它安在函数B上,甚至安在任何函数上,因为装饰器执行的是一个通用操作,与我把它安在哪个函数上基本无关。注意,这里我们说“多种函数”而不是“任意函数”,因为有些装饰器有特殊用途,并不能在任意函数身上通用。

P2 装饰器的本体

我们来看一下装饰器的结构:

def 装饰器(函数模板):
骚操作 + 函数模板 (称为wrapper)
return wrapper

所以装饰器的本质还是一个函数,这也就是为什么我们说装饰器的作用是执行一个操作,只不过和那些普通平凡的函数都不同的是,装饰器的操作是通用的。

那么问题又来了,这个”wrapper“又是什么鬼?wrapper说白了就是一系列骚操作和函数模板的集合,装饰器函数返回的就是wrapper,也就是说它返回了函数的return和你所定义的骚操作。

至于函数模板,它不是任何一个特定的函数,它只是一个泛指。我们可以来看一下wrapper的结构,这里我写的是个最通用的函数模板(通过*args和**kwargs传递任意参数):

def wrapper(*args, **kwargs):
前置操作
func = function(*args, **kwargs)(即函数模板)
后置操作
return func

func = function(*args, **kwargs) 使我们得到了函数执行的结果,无论这个函数是什么函数,而return func将结果返回,连同前后的操作一起作为wrapper扔出去。

P3 一个例子

好了,接下来我们来写个例子,一个计算执行时长的装饰器:

import time

def simple_timeit(function):
def wrapper(*args, **kwargs):
start = time.time() # 记录开始时间
func = function(*args, **kwargs)
print("用时%.4fs"%(time.time() - start)) # 输出(结束时间-开始时间)
return func
return wrapper

现在我们随便写两个函数,并给它们装上装饰器:

@simple_timeit
def sleep(): # 无参数函数
time.sleep(3)
return "Get up!!!"
@simple_timeit
def break_str(string): # 有参数函数
txt = [t.upper() for t in string.split(" ")]
return txt

执行一下看看结果:

可以看到对于不同的函数类型,我们的计时器都是通用的。

总的来说,装饰器能让我们的代码变得简洁,而且能在多个函数上通用。再者由于它是在函数之上额外附加的操作,所以我们只要将装饰器那一行注释掉就能关闭附加功能,而又不影响函数本体的功能,可以说非常方便啦,所以有机会还是值得一用的~

野路子码农(5)Python中的装饰器,可能是最通俗的解说的更多相关文章

  1. 野路子码农系列(2)Python中的类,可能是最通俗的解说

    啥叫佩奇?啥叫类?啥叫面向对象?后面两个问题以前在大学里“祖传谭浩强”的时候我经常会有所疑问.老师说着一堆什么public, private,我都是一脸懵逼,啥叫私有?为啥要私有?然后就神游天外了…… ...

  2. 野路子码农系列(1) 创建Web API

    新工作正式开始了2天,由于客户暂时还没交接数据过来,暂时无事可做.恰逢政佬给某超市做的商品图像识别的项目客户催收了,老板要求赶紧搞个API,于是我就想我来试试吧. 说起API,我其实是一窍不通的,我对 ...

  3. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  4. 【Python】python中的装饰器——@

    对装饰器本来就一知半解的,今天终于弄清楚了,Python中的装饰器是对装饰者模式的很好运用,简化到骨子里了. python中为什么需要装饰器,看这里:http://www.cnblogs.com/hu ...

  5. Python 中实现装饰器时使用 @functools.wraps 的理由

    Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过  ...

  6. 写python中的装饰器

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

  7. python中的装饰器decorator

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

  8. python中@property装饰器的使用

    目录 python中@property装饰器的使用 1.引出问题 2.初步改善 3.使用@property 4.解析@property 5.总结 python中@property装饰器的使用 1.引出 ...

  9. 【Python】解析Python中的装饰器

    python中的函数也是对象,函数可以被当作变量传递. 装饰器在python中功能非常强大,装饰器允许对原有函数行为进行扩展,而不用硬编码的方式,它提供了一种面向切面的访问方式. 装饰器 一个普通的装 ...

  10. 三分钟搞定Python中的装饰器

    python的装饰器是python的特色高级功能之一,言简意赅得说,其作用是在不改变其原有函数和类的定义的基础上,给他们增添新的功能. 装饰器存在的意义是什么呢?我们知道,在python中函数可以调用 ...

随机推荐

  1. mybatis 测试输出SQL语句到控制台配置

    1: mybatis-config.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...

  2. 抽取vs2010安装包中vc++ runtime

    写于2015-3-21 16:59 由qq空间转过来,格式有点乱     之前遇到一个问题,c++\cli的程序部署在服务器上面,程序运行后没有反应就退出了,日志管理器中记录两个错误信息分别如下:   ...

  3. Java基础之一、入门知识

    资料来源于<明解 Java>日本作者 写的很详细 1:命令---java 类名 该命令不是去执行类名.class文件(文件名和类名有可能不一致),切记是表示执行具体的类: 2:“字符”+数 ...

  4. 没有正确配置扫描包,提示spring的bean不存在

    如下提示的解决方案: <!-- 扫描org.infor包下面的java文件,有Spring的相关注解的类,则把这些类注册为Spring的bean -->  <context:comp ...

  5. ArcGIS Runtime SDK for Android 加载shp数据,中文乱码问题

    针对ArcGIS10.2版本的解决办法(默认中文编码为OEM): 现有一个图层名称为“图层.shp”,以此为例: 1.拷贝一个cpg文件,修改名称为“图层.cpg”,并用文本打开cpg文件修改编码为“ ...

  6. 我眼中的ASP.NET.MVC

    MVC MVC全名 : Model View Controller ( Model-模型 View-视图  Controller-控制器)是一种经典的,经久不衰的,屹立不倒的软件设计框架.实现了业务逻 ...

  7. P3902 递增

    链接:P3902 ----------------------------------------- 这道题就是最长上升子序列的模板题,因为我们修改的时候可没说不能改成小数(暴力) --------- ...

  8. kubernetes安装-二进制

    主要参考https://github.com/opsnull/follow-me-install-kubernetes-cluster,采用Flanel和docker 系统信息 角色 系统 CPU C ...

  9. layui弹出表单提交后,界面model验证部分起作用

    情况1----input属性中type=submit时验证都可以起作用,但是弹出层表单的返回值不能获取,所以用ajax二次提交后会出现重复添加数据的问题 情况2----input属性中type=but ...

  10. 使用 VMware Workstation Pro 安装新的虚拟机

     一.连接服务器 (1)“文件”右键 (2)输入用户名.密码连接服务器 二.创建新的虚拟机 (1) (2) (3) (4) (5) (6) (7) (8)  三.配置服务器 配置文档 - 链接:htt ...