python中的装饰器

1、闭包的理解

要完全理解装饰器,需要先从闭包开始,下面的代码应该比较好理解:

def w1(func):
    def inner():
        print("----内部函数-----")
        func()
    return inner

def f1():
    print("----f1----")

def f2():
    print("----f2----")


innerFunc = w1(f1)
innerFunc()

上面其实就是一个闭包,执行后,将输出:

----内部函数-----
----f1----

如果修改一下,是否还可以理解呢:

def w1(func):
    def inner():
        print("----内部函数-----")
        func()
    return inner

def f1():
    print("----f1----")

def f2():
    print("----f2----")


f1 = w1(f1)
f1()

2、装饰器

上面的代码输出是不会变的。需要说明的是执行完f1 = w1(f1)后,左边的f1是指向函数w1的内部函数inner()的。这里其实就是装饰器的雏形。稍微修改一下是装饰器了,如下:

def w1(func):
    def inner():
        print("----内部函数-----")
        func()
    return inner

# @w1 其实就是 f1 = w1(f1)
@w1
def f1():
    print("----f1----")

def f2():
    print("----f2----")

f1()

输出不变:

----内部函数-----
----f1----

总结:装饰器可以理解成一种特殊的闭包,将一个函数(f1)传入另个函数(w1)的内部函数(inner),并在内部函数中执行,在执行过程中内部函数可以对传入的函数进行一个功能扩展。需要说明的是,以上面的代码为例,程序运行到f1()之前,@w1是会先执行的,也就是说会先执行f1 = w1(f1)这句。

3、完整的小例子

3.1 普通例子

def makeBold(fn):
    def wrapped():
        print("----1----")
        return "" + fn() + ""
    return wrapped

def makeItalic(fn):
    def wrapped():
        print("----2----")
        return "" + fn() + ""
    return wrapped

@makeBold
@makeItalic
def test():
    print("----3----")
    return "hello world"

ret = test()
print(ret)

输出如下:

----1----
----2----
----3----
hello world

3.2 带参数、返回值装饰器

# 可以有参数,可以有返回值的装饰器
def func(functionName):
    def func_in(*args, **kwargs):
        ret = functionName(*args, **kwargs)
        return ret
    return func_in


@func
def test1():
    print("----无参数,无返回值----")

@func
def test2():
    print("----无参数,有返回值----")
    return "返回值:test2"

@func
def test3(a):
    print("----有参数,有返回值----")
    return "返回值:{}".format(a)

test1()
print(test2())
print(test3(666))

输出:

----无参数,无返回值----
----无参数,有返回值----
返回值:test2
----有参数,有返回值----
返回值:666

3.3 特殊的装饰器

def func_arg(arg):
    def func(functionName):
        def func_in():
            if arg == "装饰器参数":
                functionName()
            else:
                print(arg)
        return func_in
    return func


# 注意是先执行func_arg("装饰器参数")函数,然后返回func,再执行@func
@func_arg("装饰器参数")
def test1():
    print("----传递装饰器的参数----")

@func_arg("不传值")
def test2():
    pass

test1()
test2()

输出:

----传递装饰器的参数----
不传值

 

你可能感兴趣的:(Python)