什么是装饰器?

python装饰器(fuctional decorators)就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。

这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌“原“”函数的函数。

一般而言,我们要想拓展原来函数代码,最直接的办法就是侵入代码里面修改,例如:

import time
def f():
print("hello")
time.sleep(1)
print("world")

这是我们最原始的的一个函数,然后我们试图记录下这个函数执行的总时间,那最简单的做法就是改动原来的代码:

import time
def f():
start_time = time.time()
print("hello")
time.sleep(1)
print("world")
end_time = time.time() execution_time = (end_time - start_time)*1000
print("time is %d ms" %execution_time)

但是实际工作中,有些时候核心代码并不可以直接去改,所以在不改动原代码的情况下,我们可以再定义一个函数。(但是生效需要再次执行函数)

import time

def deco(func):
start_time = time.time()
f()
end_time = time.time()
execution_time = (end_time - start_time)*1000
print("time is %d ms" %execution_time) def f():
print("hello")
time.sleep(1)
print("world") if __name__ == '__main__': deco(f)
print("f.__name__ is",f.__name__)
print()

这里我们定义了一个函数deco,它的参数是一个函数,然后给这个函数嵌入了计时功能。但是想要拓展这一千万个函数功能,

就是要执行一千万次deco()函数,所以这样并不理想!接下来,我们可以试着用装饰器来实现,先看看装饰器最原始的面貌。

import time

def deco(f):
def wrapper():
start_time = time.time()
f()
end_time = time.time()
execution_time = (end_time - start_time)*1000
print("time is %d ms" %execution_time )
return wrapper @deco
def f():
print("hello")
time.sleep(1)
print("world") if __name__ == '__main__':
f()

这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。

其中作为参数的这个函数f()就在返回函数wrapper()的内部执行。然后在函数f()前面加上@deco,

f()函数就相当于被注入了计时功能,现在只要调用f(),它就已经变身为“新的功能更多”的函数了,

(不需要重复执行原函数)。

扩展1:带有固定参数的装饰器

import time

def deco(f):
def wrapper(a,b):
start_time = time.time()
f(a,b)
end_time = time.time()
execution_time = (end_time - start_time)*1000
print("time is %d ms" % execution_time)
return wrapper @deco
def f(a,b):
print("be on")
time.sleep(1)
print("result is %d" %(a+b)) if __name__ == '__main__':
f(3,4)

扩展2:无固定参数的装饰器

import time

def deco(f):
def wrapper(*args, **kwargs):
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execution_time_ = (end_time - start_time)*1000
print("time is %d ms" %execution_time)
return wrapper @deco
def f(a,b):
print("be on")
time.sleep(1)
print("result is %d" %(a+b)) @deco
def f2(a,b,c):
print("be on")
time.sleep(1)
print("result is %d" %(a+b+c)) if __name__ == '__main__':
f2(3,4,5)
f(3,4)

扩展3:使用多个装饰器,装饰一个函数

import time

def deco01(f):
def wrapper(*args, **kwargs):
print("this is deco01")
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execution_time = (end_time - start_time)*1000
print("time is %d ms" % execution_time)
print("deco01 end here")
return wrapper def deco02(f):
def wrapper(*args, **kwargs):
print("this is deco02")
f(*args, **kwargs) print("deco02 end here")
return wrapper @deco01
@deco02
def f(a,b):
print("be on")
time.sleep(1)
print("result is %d" %(a+b)) if __name__ == '__main__':
f(3,4)
'''
this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1003 ms
deco01 end here
'''

装饰器调用顺序:

饰器是可以叠加使用的,那么使用装饰器以后代码是啥顺序呢?

对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。

在这个例子中,”f(3, 4) = deco01(deco02(f(3, 4)))”。

Python内置装饰器

在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。

  • staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
  • classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
  • property 是属性的意思,表示可以通过通过类实例直接访问的信息

对于staticmethod和classmethod这里就不介绍了,通过一个例子看看property。

注意,对于Python新式类(new-style class),如果将上面的 “@var.setter” 装饰器所装饰的成员函数去掉,则Foo.var 属性为只读属性,使用 “foo.var = ‘var 2′” 进行赋值时会抛出异常。但是,对于Python classic class,所声明的属性不是 read-only的,所以即使去掉”@var.setter”装饰器也不会报错。

【转】python装饰器的更多相关文章

  1. 关于python装饰器

    关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...

  2. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  3. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  4. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  5. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  6. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  7. 关于python装饰器(Decorators)最底层理解的一句话

    一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...

  8. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  9. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

  10. python装饰器方法

    前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...

随机推荐

  1. 【C语言】scanf()输入浮点型数据

    #include<stdio.h> int main() { double x1, x2, x3, x4; printf("输入2个浮点数x1,x2:\n"); sca ...

  2. maven的安装与使用(运行单元测试和打包等)

    maven的下载与安装 maven是用于java的自动化构建工具. 1.下载: http://maven.apache.org/download.cgi 下载maven包,比如 apache-mave ...

  3. tkinter学习(5)messagebox、pack、grid和place方法

    1.messagebox信息弹出框 1.1 代码: import tkinter as tk #导出tk模块 import tkinter.messagebox #导出弹出信息框 #定义窗口.标题.大 ...

  4. Go标准库之Log

      文章引用自 Go语言标准库log介绍 无论是软件开发的调试阶段还是软件上线之后的运行阶段,日志一直都是非常重要的一个环节,我们也应该养成在程序中记录日志的好习惯. log Go语言内置的log包实 ...

  5. 用for循环创建对象

    以下代码Demo: public class TestDemo { public static void main(String[] args) { //以创建5个student为例 int coun ...

  6. 【MySQL】安装及配置

    " 目录 #. 概述 1. 什么是数据(Data) 2. 什么是数据库(DataBase, 简称DB) 3. 什么是数据库管理系统(DataBase Management System) 4 ...

  7. python正则表达式中括号的作用,形如 "(\w+)\s+\w+"

    先看一个例子: import re string="abcdefg acbdgef abcdgfe cadbgfe" #带括号与不带括号的区别 regex=re.compile(& ...

  8. html和css的重难点知识

    目录 html总难点总结: 1. 块级标签与内联标签的区别 1.1 块级标签: 1.2 内联标签: 2. 选择器 2.1 定义 2.2 选择器的分类 2.1 选择器的分类 3. css中margin, ...

  9. 对于java中反编译命令的使用以及Integer包装类的查看

    Integer是基于int的包装类 我们可以用测试代码来看看Integer类是如何实现装箱和拆箱的 public class BoxAndUnbox { /** * @param args */ pu ...

  10. Linux批量装机(PXE)!

    一 .PXE 简介PXE:Pre-boot Excution Environment,预启动执行环境PXE 是由 Intel 公司开发的网络引导技术,工作在 Client/Server 模式,允许客户 ...