首页 » 编程 » Python » 正文

装饰器

day22


为什么要用装饰器及开放封闭原则

什么是装饰器

装饰着:可调用对象-是函数

被装饰着:可调用对象-也是函数


分为 无参装饰器 和 有参装饰器


例子:

如下函数:

import time

def index():
    time.sleep(3)
    print("welcome to my function")

index()

如何在不改变函数代码的情况下添加函数的执行时间功能?

修改如下:

import time

def timmer(func):
    def wrapper():
        start = time.time()
        func()
        stop = time.time()
        print("run time is %s" % (stop - start))
    return wrapper


@timmer      # 相当于 index = timmer(index)
def index():
    time.sleep(3)
    print("welcome to my function")

index()


如上:timmer就是装饰器


如何使用装饰器:

在被装饰函数的正上方加上@装饰器的名字,如@timmer


干了什么事情?

他回将他下面的函数的名字当做参数传给装饰器,将返回值返回给函数名,相当于 index = timmer(index)

最后运行结果:

welcome to my function
run time is 3.0008106231689453


整合例子(无参装饰器):

import time

import time


def timmer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        stop = time.time()
        print("run time is %s" % (stop - start))
        return res

    return wrapper


@timmer  # 相当于 index = timmer(index)
def index():
    time.sleep(3)
    print("welcome to my function")


@timmer
def auth(username, password):
    print(username, password)


@timmer
def my_max(x, y):
    print("开始计算结果.., from my_max")
    res = x if x > y else y
    return res


index()
auth("alex", "123")

number = my_max(1, 2)
print("结果为:", number)

说明:

给装饰器加上*args和**kwargs后,可接受多个参数。

给装饰器加上接收值后 res = func(*args, **kwargs) 可将源函数的返回值返回


运行结果:

welcome to my function
run time is 3.000807046890259
alex 123
run time is 0.0
开始计算结果.., from my_max
run time is 0.0
结果为: 2



整合例子(有参装饰器):

import time


def timmer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        stop = time.time()
        print("run time is %s" % (stop - start))
        return res

    return wrapper


def auth2(auth_type):
    def auth(func):
        def wrapper(*args, **kwargs):

            if auth_type == "file":
                name = input("name:")
                password = input("password:")
                if name == "alex" and password == "123":
                    res = func(*args, **kwargs)
                    return res
                else:
                    print("auth faild")
            elif auth_type == "sql":
                print("开始执行查询数据库,还没学。。")

        return wrapper

    return auth

@timmer
@auth2(auth_type="file")
def home():
    print("welome to home page.")


@auth2(auth_type="sql")
def shop():
    print("welome to shop page.")


home()
shop()

运行结果:

name:alex
password:123
welome to home page.
run time is 4.565687894821167
开始执行查询数据库,还没学。。


@timmer
@auth2(auth_type="file")

表示被2个装饰器装饰,顺序先执行auth2,再执行timmer


如何显示原函数的注释信息:

如下测试:

import time


def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        stop_time = time.time()
        print("run time is %s" % (stop_time - start_time))
        return res

    return wrapper


@timer
def test():
    "this is function decsription.."
    print("test function")


test()
print(test.__doc__)

运行结果:

test function
run time is 0.0
None


加上装饰器后,函数注释信息无法获取到,这时需要导入新的模块将装饰器再调用装饰器

import time
from functools import wraps  # 导入模块用于处理函数注释信息


def timer(func):
    @wraps(func)  # 调用装饰器
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        stop_time = time.time()
        print("run time is %s" % (stop_time - start_time))
        return res

    return wrapper


@timer
def test():
    "this is function decsription.."
    print("test function")


test()
print(test.__doc__)  # 打印注释函数注释信息

运行结果:

test function
run time is 0.0
this is function decsription..


赞 (0)

发表评论

*