装饰器

# 首先介绍闭包(理解闭包是理解装饰器的前提)
# 什么是闭包呢?在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def test01(num):
    def test02():
        print("num is %d" % num)

    return test02


ret = test01(20)
ret()
print("*" * 60)


# 装饰器的理解
# 需求:在不更改源代码的情况下,对原来的方法添加一些验证。比如:flag==1 才执行 test01()等等
# 装饰器的应用场景:
# 1、引入日志
# 2、函数执行时间统计(这个可以常用啊)
# 3、执行函数前预备处理
# 4、执行函数后清理功能
# 5、权限校验等场景
# 6、缓存

# 无参数的装饰器
def test03(func):
    print("-----1-----")

    def test04():
        print("-----2-----")
        func()

    return test04


# @test03 等价于下面这两句话
# test05 = test03(test05)
# test05()
@test03
def test05():
    print("-----3-----")


test05()
print("*" * 60)


# 注意:装饰的函数是带参函数时,返回的test07()也必须是代参函数,用来接收
# 被装饰的函数有参数
def test06(func):
    print("-----1-----")

    def test07(name, age):
        print("-----2-----")
        func(name, age)

    return test07


@test06
def test08(name, age):
    print("-----3-----")
    print("name is %s, %d" % (name, age))


test08("张三", 15)
print("*" * 60)


# 通用的装饰器函数,不论它是有参还是无参,有返回值还是无返回值,都是通用的
# args——存放元组参数,前面有一个*
# kwargs——存放字典参数,前面有两个*
# 补充:元组和字典的拆包:如果希望将一个元组或者字典直接传给函数,可在参数名前面加一个*或者两个*
def test09(func):
    print("-----1-----")

    def test10(*args, **kwargs):
        print("-----2-----")
        ret = func(*args, **kwargs)
        return ret

    return test10


@test09
def test11(*args, **kwargs):
    print("-----3-----")
    return args, kwargs


print(test11(*("腾讯", "阿里巴巴", "谷歌"), **{"张三": 15, "李四": 16, "王五": 17}))
print("*" * 60)


# 两个装饰器,首先看到第一个@test12,但是呢?发现下面还有一个@test14,而装饰器是用来装饰函数的,不能用来装饰@test14
# 所以要等下面的@test14装饰完了之后,@test12才能再装饰
# 两个装饰器(理解)
def test12(func):
    print("-----1-----")

    def test13():
        print("-----2-----")
        return "hello " + func()

    return test13


def test14(func):
    print("-----3-----")

    def test15():
        print("-----4-----")
        return "python " + func()

    return test15


@test12
@test14
def test16():
    print("-----5-----")
    return "world"


print(test16())
print("*" * 60)


# 1、因为装饰器带了参数,首先是直接调用timefun_arg(),返回了timefun,此时的@timefun_arg("itcast")就变成了@timefun
# 2、然后才装饰foo()函数
# 3、后面的步骤如上
def test17(str="hello"):
    def test18(func):
        def test19():
            print("%s" % str)
            return func()

        return test19

    print(str)
    return test18


@test17("hello world")
def test20():
    print("this is python world")


test20()
print("*" * 60)


# 类装饰器(了解)
# 要想理解类装饰器,首先需要理解下面这段代码
class test21(object):
    def __call__(self):
        print('call me!')


t = test21()
t()
# t是一个对象,又不是一个方法,怎么可以t()呢?
# 原来t()会默认调用__call__(self)方法,因为类test21重写了__call__(self)方法,所以调用重写后的
print("*" * 60)


# 接下来才是类装饰器(不得不说动态语言真是花里胡哨)
class test22(object):
    def __init__(self, func):
        print("---初始化---")
        print("func name is %s" % func.__name__)
        self.__func = func

    def __call__(self):
        print("---装饰器中的功能---")
        self.__func()


@test22
def test():
    print("----test---")


test()

 

posted @ 2018-11-12 18:36  人工智能之路上的菜鸡  阅读(158)  评论(0编辑  收藏  举报