python装饰器的学习理解
自己的理解
装饰器是python语言中的高阶函数,被装饰的函数嵌套在装饰器内部,其目的可实现对被装饰函数的功能扩充。
举个例子,加深理解
任务:完成对执行函数func1的执行时间的记录
不用装饰器实现
# -*- coding: utf-8 -*-
import time
def func1(): s_time = time.time() time.sleep(1) e_time = time.time() print "执行func1 需要时间 %s" % (e_time - s_time) if __name__ == "__main__": func1() ######执行结果如下######## 执行func1 需要时间 1.00396990776
但是这样写问题是: 如果类似对func1增加记录执行时间的函数很多,怎么办,难道要所有都修改一遍函数内的代码么,这太low,改进一下,把记录执行时间的功能做成一个函数,如下所示
# -*- coding: utf-8 -*-
import time
def get_time(func): s_time = time.time() func() e_time = time.time() print "执行%s 需要时间 %s" % (func.__name__, (e_time - s_time)) def func1(): time.sleep(1) def func2(): time.sleep(2) if __name__ == "__main__": get_time(func1) get_time(func2) ######执行结果如下###### 执行func1 需要时间 1.00424098969 执行func2 需要时间 2.00435495377
这种函数调用固然好,但是依然存在我要写上函数(get_time),能不能有办法,我只写func,不改变其内部代码的情况下,就能实现功能的扩充。能,那就装饰器吧。。。
# -*- coding: utf-8 -*-
import time
def get_time(func): def inner(): s_time = time.time() func() e_time = time.time() print "执行%s 需要时间 %s" % (func.__name__, (e_time - s_time)) return inner def func1(): time.sleep(1) @get_time # 语法糖 def func2(): time.sleep(2) if __name__ == "__main__": func1 = get_time(func1) func1() func2() # @get_time 等价于 func2 = get_time(func2); func2() ####执行结果如下#### 执行func1 需要时间 1.00032997131 执行func2 需要时间 2.00419783592
上边执行顺畅了,但是如果想传参数怎么办呢。。。
# -*- coding: utf-8 -*-
import time
def get_time(func): def inner(*args, **kwargs): s_time = time.time() func(*args, **kwargs) e_time = time.time() print "执行%s 需要时间 %s" % (func.__name__, (e_time - s_time)) return inner @get_time # 语法糖 def func1(x, y): time.sleep(1) print x, y if __name__ == "__main__": func1(1, 2)
如果func1函数,不是print 而是想return 上边的装饰是否仍能work呢,答案是不行,需要对get_time装饰器再做处理
# -*- coding: utf-8 -*-
import time
# 完整的装饰器 def get_time(func): def inner(*args, **kwargs): s_time = time.time() res = func(*args, **kwargs) e_time = time.time() print "执行%s 需要时间 %s" % (func.__name__, (e_time - s_time)) return res return inner @get_time # 语法糖 def func1(x, y): time.sleep(1) return x, y if __name__ == "__main__": tmp = func1(1, 2) print tmp
python 一些内置的装饰器
- @staticmethod
- @classmethod
- @property
- @abstractmethod
@staticmethod
自己理解:该装饰器可将类中的方法不用写参数self, 并且使用该类中的方法时不用实例化,可直接用类调用。 静态方法
应用场景:如果在方法中不需要访问任何实例方法和属性,纯粹地通过传入参数并返回数据的功能性方法,那么它就适合用静态方法来定义,它节省了实例化对象的开销成本,往往这种方法放在类外面的模块层作为一个函数存在也是没问题的,而放在类中,仅为这个类服务。
class C: @staticmethod def f(): print "hello " if __name__ == "__main__": C.f() c = C() c.f()
@classmethod
自己理解:该装饰器可将类中的方法装饰起来,使得调用时不用对类实例化。类方法
class A(object): bar = 1 def func1(self): print ('foo')
@classmethod def func2(cls): print ('func2') print (cls.bar) cls().func1() # 调用 foo 方法 if __name__ == "__main__": A.func2() # 不需要实例化
@property
自己理解:对于一个类的属性,python的访问是没有限制的,但有时候我们需要对属性的访问加以限制,property装饰器就是干这个的。有三个方法,deleter,setter,getter(property 取代之)。
class C: @property def width(self): return self._width @width.setter def width(self, value): self._width = value @width.deleter def width(self): del self._width
@abstractmethod
自己理解:含abstractmethod方法的类,不能被实例化,继承该类的子类带有abstractmethod方法的都要重写。
from abc import ABCMeta, abstractmethod class A: @abstractmethod def write(self): pass class B(A): def write(self): print "hello b" if __name__ == "__main__": b = B() b.write()