zoukankan      html  css  js  c++  java
  • 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()
    

     

      

  • 相关阅读:
    JDK自动安装脚本
    lamp script
    spring MVC multipart处理文件上传
    在Java中定义常量
    常用服务搭建(nfs/ftp/samba)
    源码编译安装mysql5.6
    Spring MVC
    Linux crontab 命令格式与详细例子
    Linux : IPTABLES
    linux monitor and maintanence
  • 原文地址:https://www.cnblogs.com/syw-home/p/12367507.html
Copyright © 2011-2022 走看看