Python里面的装饰器

  • 使用装饰器的目的:为了减少冗余代码
  • 比如我们需要输出一个函数的运行时间,最简单的方法就是在函数中写入计算时间的代码比如下面的做法,但是如果现在我们需要让每一个函数都输出自己的的运行时间,按照上面的做法无疑需要写许多一样的代码,为了减少代码冗余,就需要一个装饰器来一劳永逸的解决这个问题了。
  • 装饰器的作用就相当于在函数的两边嵌入了其他代码,起到“装饰”函数的作用。
#普通解决方法
def add(a,b):
    startTime=time.time()
    c=a+b
    endTime=time.time()
    print("time:",endTime-startTime)
    print(c)
def minus(a,b):
    startTime=time.time()
    c=a-b
    endTime=time.time()
    print("time:",endTime-startTime)
    print(c)
  • 如果所有的函数传入参数的数目固定的,装饰器可以这么写,不过这种情况比较少,写出来只是为了帮助理解装饰器的作用原理。
def showTime(func):
    def wrapper(a,b):
        since=time.time()
        func(a,b)
        endtime=time.time()
        print("time:",since-endtime)
    return wrapper

@showTime
def add(a,b):
   print(a+b)
@showTime
def minus(a,b):
   print(a-b)

add(1,2)
minus(1,2)
  • 对于函数的传入参数是不一样长的情况,装饰器这么写。
def showTime(func):
    def wrapper(*args,**kwargs):
        since=time.time()
        func(*args,**kwargs)
        endtime=time.time()
        print("time:",since-endtime)
    return wrapper

@showTime
def add(a,b):
    print(a+b)
def minus(a,b,c):
    print(a-b-c)

add(1,2)
minus(1,2,3)
  • 一个例子
def disk_memoize(func):
    cache_dir = os.path.join(BASE_DIR, "_cache")
    if not os.path.exists(cache_dir):
        os.makedirs(cache_dir)

    @functools.wraps(func)
    def wrapper_decorator(*args, **kwargs):
        # check fn arguments
        args_str = ''.join(args_to_str(args))
        key = hashlib.md5(args_str.encode()).hexdigest()
        cache_file = os.path.join(cache_dir, key)

        if os.path.exists(cache_file):
            print(f"Loading {cache_file} from cache!")
            with open(cache_file, 'rb') as f:
                return pickle.load(f)
        else:
            print(f"No cache file for {cache_file}...")
            data = func(*args, **kwargs)

            with open(cache_file, 'wb') as pickle_file:
                pickle.dump(data, pickle_file)

            return data

    return wrapper_decorator

# @disk_memoize
def read_corpus(file, tokenize):
    _vocab = Vocab()

    _data = []
    for line in iterate_data(file):
        tokens = tokenize(line)
        _vocab.read_sequence(tokens)
        _data.append(tokens)

    return _vocab, _data

你可能感兴趣的:(Python里面的装饰器)