修改其他函数的功能的神器——python装饰器

1.函数装饰器介绍

装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。

所谓“语法糖”指的是编程语言中对功能没有影响但是能显著提高易用性和可读性的特殊语法,本文要谈到的“装饰器”是python最重要的语法糖,没有之一。

当需要对已有的函数添加额外的功能时:

  • 个人程序-直接修改代码
  • 函数封装-创建新封装函数
  • 装饰器处理

2.个人程序

#对已有的函数添加额外的功能
#比如为整个程序添加个计时功能
import random
import time
#从1-10**8中随机挑选n个数,并从小到大排序
def getList(n):
    # 开始前计时
    start_time=time.time()
    seq=list(range(1,pow(10,6)))
    x=random.sample(seq,n)
    y=sorted(x)
    # 结束后计时
    end_time=time.time()
    print("Time userd:%s"%(end_time-start_time))
    return y
result=getList(1000)
print(len(result),type(result))

如果是个人程序,这样的解决方案无可厚非,
但如果是集体开发的大型项目,这样的改动通常是不被允许的,
如果大家都为了各自的需求在原函数中添加代码,很可能会造成灾难性的后果。
还有一种解决方案,就是将原函数封装到一个新的函数中,
在新函数中对原函数的运行时间进行计算。

3.函数封装

import random
import time
#从1-10**8中随机挑选n个数,并从小到大排序
def getList(n):
    seq=list(range(pow(10,6)))
    x=random.sample(seq,n)
    y=sorted(x)
    return y
def getListTime(n):
    # 开始前计时
    start_time=time.time()
    r=getList(n)
    # 结束时计时
    end_time=time.time()
    print("Time userd:%s"%(end_time-start_time))
    return r
result=getListTime(10000)
print(len(result),type(result))

上面代码中使用getListTime( )函数对getList( )函数进行了封装,
在getList( )函数执行前和结束后分别计时,然后求得函数耗时。
这种方案不用修改原函数中的代码,
看似可行,实际上存在很多的问题。使用该方案

  • 不仅需要为每一个需要功能拓展的函数分别新建一个新函数,
  • 而且还要修改所有的调用,
  • 如果需要功能拓展的函数有成百上千个,可想而知会带来多大的工作量。

如何简洁优雅地实现函数的功能拓展呢?python中最佳方案是“装饰器”。

4.“装饰器”处理

import random
import time
#从1-10**8中随机挑选n个数,并从小到大排序
def getList(n):
    seq=list(range(pow(10,6)))
    x=random.sample(seq,n)
    y=sorted(x)
    return y
def getTuple(n):
    seq=list(range(pow(10,6)))
    x=random.sample(seq,n)
    y=tuple(sorted(x))
    return y
def getListTime(func):
    def wrapper(n):
        # 开始前计时
        start_time=time.time()
        r=func(n)
        # 结束时计时
        end_time=time.time()
        print("Time userd:%s"%(end_time-start_time))
        return r
    return wrapper
# result=getListTime(getList)(100)
result=getListTime(getTuple)(100)
print(len(result),type(result))

# 装饰器函数,使用函数作为参数
def decorator(func):
    def wrapper(n):
        start_time=time.time()
        r=func(n)
        end_time=time.time()
        print("Time userd:%s"%(end_time-start_time))
        return r
    return wrapper

@decorator
def getList(n):
    seq=list(range(pow(10,6)))
    x=random.sample(seq,n)
    y=sorted(x)
    return y
result=getList(100)
# result=getListTime(getTuple)(100)
print(len(result),type(result))

# 给多个函数添加装饰器
@decorator
def getTuple(n):
    seq=tuple(range(pow(10,6)))
    x=random.sample(seq,n)
    return tuple(x)
result=getTuple(100)
print(len(result),type(result))


# 给多参数函数添加装饰器
def decorator(func):# 1,2,3 ,host=‘localhost’ password='123456'
    def wrapper(*args,**kwargs):
        start_time=time.time()
        r=func(*args,**kwargs)
        end_time=time.time()
        print("Time userd:%s"%(end_time-start_time))
        return r
    return wrapper
@decorator
def add_two_number(a,b):
    return a+b
@decorator
def getTuple(n):
    seq=tuple(range(pow(10,8)))
    x=random.sample(seq,n)
    return tuple(x)
add_two_number(1,2)
r=getTuple(100)

# 使用多个装饰器装饰一个函数
def decorator1(func):
    def wrapper(*args,**kwargs):
        print("first dec start!")
        r=func(*args,**kwargs)
        print("first dec end!")
        return r
    return wrapper
def decorator2(func):
    def wrapper(*args,**kwargs):
        print("second dec start!")
        r=func(*args,**kwargs)
        print("second dec end!")
        return r
    return wrapper

@decorator1
@decorator2
def add_two_number(a,b):
    return a+b
add_two_number(100,200)

猜你喜欢

转载自blog.csdn.net/qq_35866846/article/details/107834339