zoukankan      html  css  js  c++  java
  • [python]python进阶编程(3)-装饰器

    说明

    前面我们提到了闭包的概念,闭包是python的一个重要特性,而装饰器是闭包的一个重要应用。

    闭包

    闭包即为返回值为函数的函数。示例程序如下所示:

    def num(num):
    	def num_in(num2): 
    		return num + num2 
    	return num_in #返回函数
     
    a = num(100) # a是一个函数。
    b = a(100) # 110 。
    

    装饰器

    在一些需要对已有函数进行修改但是不改变原有函数功能场景中,比如对某个函数的运行进行计时,打log等,就需要用到装饰器函数了。

    无参装饰器

    无参装饰器即为装饰器本身没有参数,那么其运行时也是最简单的,即为两层的闭包。以下程序示例:

    def timer(fun):
        def run():
            t1 = time.time()
            fun()
            run_time = time.time() - t1
            print('程序运行时间为', run_time)
        return run
    
    def funs():
        time.sleep(1)
        print('无参函数')
    
    funs()
    funs = timer(funs)  # 使函数调用没有发生变化,但是多了统计运行时间功能
    funs()
    
    @timer  # 在函数声明时加入语法糖,等同于funs = timer(funs)
    def funs():
    

    以上的过程为一个简单装饰器的使用过程,而调用过程分为有语法糖的调用,以及没有语法糖的调用。上述的示例展示了装饰无参函数的装饰器,那么如果使用有参有返回值的的装饰器应该怎么写?以下程序示例:

    def timer(fun):
        def run(*args, **kwargs): # 不定长参数
            t1 = time.time()
            out = fun(*args, **kwargs)
            run_time = time.time() - t1
            print('程序运行时间为', run_time)
            return out
        return run
    
    def funs(a, b):
        time.sleep(1)
        return a + b
    
    print(funs(3, 5))
    funs = timer(funs)
    print(funs(3, 5))
    
    

    有参装饰器

    在某些情况下,需要对装饰器传入参数,比如在统计时间时,有的程序要求统计单位为ms,有的要求为s,那么就可以通过有参的装饰器来实现:

    def var_timer(ns=1000):
        def timer(fun):
            def run(*args, **kwargs):
                t1 = time.time()
                out = fun(*args, **kwargs)
                run_time = time.time() - t1
                print('程序运行时间为', run_time * ns)
                return out
            return run
        return timer
    
    @var_timer(1000) # 注意此时统计的是ms,当然也可以统计ns和s
    def funs(a, b):
        time.sleep(1)
        return a + b
    print(funs(3, 5))
    

    内置装饰器

    常见的内置装饰器有三种,@property、@staticmethod、@classmethod。

    @property
    把类内方法当成属性来使用,必须要有返回值,相当于getter;
    假如没有定义 @func.setter 修饰方法的话,就是只读属性。

    @staticmethod
    静态方法,不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样,静态方法通常维护一个共同的静态量。

    @classmethod
    类方法,不需要self参数,但第一个参数需要是表示自身类的cls参数。

  • 相关阅读:
    IO
    mouseover,mouseout和mouseenter,mouseleave
    【译】addEventListener 第二个参数
    Git 常用命令
    我对Backbone中url属性的理解
    小失误引起大失败
    收集各大网站的登录页面
    随笔2
    随笔1
    创建数据库
  • 原文地址:https://www.cnblogs.com/wildkid1024/p/13218592.html
Copyright © 2011-2022 走看看