Python 装饰器

Python 装饰器

取得成就时坚持不懈,要比遭到失败时顽强不屈更重要。——拉罗什夫科

  • python 装饰器(function 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 {0} s starttime is {1} endtime is {2}'.format(execution_time ,start_time,end_time))
  • 但是实际情况是,有些时候核心代码并不能直接修改,所以在不修改源代码的情况下,我们可以在定义一个函数(但是生效的时候需要再次执行函数)

import time

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

def deco(f):
  start_time = time.time()
  f() #执行核心函数
  end_time = time.time()
  execution_time = (end_time-start_time)*1000
  print('time is {0} s starttime is {1} endtime is {2}'.format(execution_time ,start_time,end_time))

deco(f) # 调用函数

这里我们定义了一个函数 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 {0} s starttime is {1} endtime is {2}'.format(
            execution_time, start_time, end_time))
    return wrapper


@deco
def f():
    print('Hello')
    time.sleep(1)
    print('World!')


f()

这里的 deco 函数就是最原始的装饰器,他的参数是一个函数,返回值也是一个函数其中作为参数的这个函数 f()就在返回函数 wrapper()的内部执行.然后再函数 f()前面加上@deco,f()函数就相当于被注入了计时功能,现在只要调用 f(),它就已经变身为’新的功能更多’的函数了

使用多个装饰器,装饰一个函数


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))



f(3,4)

装饰器调用顺序

装饰器是可以叠加使用的,对于 Python 中的@语法糖,装饰器的调用顺序与使用@语法糖声明的顺序是相反的。在这个例子中’f(3,4)=deco01(deco02(f(3,4)))’

Python 内置装饰器

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

  • staticmethod 是类静态方法其跟成员的方法区别就是没有 self 参数,并且可以在类不进行实例化的情况下调用

  • classmethod 与成员方法的区别在于它所接收的第一个参数不是 self(类实例化指针)而是 cls(当前类的具体类型)

  • property 是属性的意思。标识可以通过类实例直接访问的信息


class Foo(obj):
   def __init__(self,var):
     super(Foo,self).__init__()
     self._var = var
   @property
   def var(self):
     return self._var
   @var.setter
   def var(self,var):
     self._var = var

foo = Foo('var 1')

print(foo.var)

foo.var = 'var 2'

print foo.var

文章作者: 雾烟云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 雾烟云 !
  目录