python装饰器

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 一些内置的装饰器

  1. @staticmethod
  2. @classmethod
  3. @property
  4. @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()

 

 

  

上一篇:3.20---函数对象与闭包函数应用


下一篇:warning: implicit declaration of function 'func1' [-Wimplicit-function-declaration]