装饰器
在不改动源代码的情况下,给函数添加一个额外的功能
def fun():
    def inner():
        print("额外的功能")
    return inner
@fun
def game():
    print("这是函数原有的功能")
执行顺序
多个装饰器时:
从下向上执行
def fun_1(fun):
    def func(*args, **kwargs):
        print("--我在函数内层--1, 额外的功能-1")
        fun()
    print("--我在外层")
    return func
def fun_2(fun):
    def func(*args, **kwargs):
        print("--我是函数内层——2, 额外的功能--2")
        fun()
    print("--我在第二个装饰器外层")
    return func
@fun_1
@fun_2
def func_for():
    print("--我是第一个函数")
func_for()
# 我在第二个装饰器外层
# 我在外层
# 我在函数内层--1, 额外的功能-1
# 我是函数内层——2, 额外的功能--2
# 我是第一个函数
携带参数
当装饰器携带参数时,参数怎么用,怎么传,这里分不同情况
无参数的函数
from time import ctime
def time_fun(func):
    def wrapped_func():
        print("%s called at %s" % (func.__name__, ctime()))
        func()
    return wrapped_func
@time_fun
def foo():
    print("I am foo")
foo()
# foo called at Sat Apr  4 17:50:03 2020
# I am foo
被装饰的函数有参数
from time import ctime
def time_fun(func):
    def wrapped_func(a, b):
        print("%s called at %s" % (func.__name__, ctime()))
        print(a, b)
        func(a, b)
    return wrapped_func
@time_fun
def foo(a, b):
    print(a + b)
foo(3, 5)
# foo called at Sat Apr  4 17:50:59 2020
# 3 5
# 8
被装饰的函数有不定长参数
from time import ctime, sleep
def time_fun(func):
    def wrapped_func(*args, **kwargs):
        print("%s called at %s" % (func.__name__, ctime()))
        func(*args, **kwargs)
    return wrapped_func
@time_fun
def foo(a, b, c):
    print(a + b + c)
foo(3, 5, 7)
sleep(1)
foo(2, 4, 9)
# foo called at Sat Apr  4 17:53:31 2020
# 15
# foo called at Sat Apr  4 17:53:32 2020
# 15
装饰器中的return
from time import ctime, sleep
def time_fun(func):
    def wrapped_func():
        print("%s called at %s" % (func.__name__, ctime()))
        func()
    return wrapped_func
@time_fun
def foo():
    print("I am foo")
@time_fun
def getInfo():
    return '----hahah---'
foo()
sleep(2)
foo()
print(getInfo())
# foo called at Sat Apr  4 17:54:04 2020
# I am foo
# foo called at Sat Apr  4 17:54:06 2020
# I am foo
# getInfo called at Sat Apr  4 17:54:06 2020
# None
装饰器带参数,在原有装饰器的基础上,设置外部变量
from time import ctime, sleep
def time_fun_arg(pre="hello"):
    def time_fun(func):
        def wrapped_func():
            print("%s called at %s %s" % (func.__name__, ctime(), pre))
            return func()
        return wrapped_func
    return time_fun
# 下面的装饰过程
# 1. 调用time_fun_arg("spider")
# 2. 将步骤1得到的返回值,即time_fun返回, 然后time_fun(foo)
# 3. 将time_fun(foo)的结果返回,即wrapped_func
# 4. 让foo = wrapped_fun,即foo现在指向wrapped_func
@time_fun_arg("spider")
def foo():
    print("I am foo")
@time_fun_arg("python")
def too():
    print("I am too")
foo()
sleep(1)
foo()
too()
sleep(1)
too()
# foo called at Sat Apr  4 18:04:00 2020 itcast
# I am foo
# foo called at Sat Apr  4 18:04:02 2020 itcast
# I am foo
# too called at Sat Apr  4 18:04:02 2020 python
# I am too
# too called at Sat Apr  4 18:04:04 2020 python
# I am too
类装饰器
class Test(object):
    def __init__(self, func):
        print("---初始化---")
        print("func name is %s" % func.__name__)
        self.__func = func
    def __call__(self):
        print("---装饰器中的功能---")
        self.__func()
@Test
def test():
    print("----test---")
# ---初始化---
# func name is test
# ---装饰器中的功能---
# ----test---
- 说明:
- 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
- 并且会把test这个函数名当做参数传递到__init__方法中
- 即在__init__方法中的属性__func指向了test指向的函数
 
- test指向了用Test创建出来的实例对象
- 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法
- 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用
- 所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体
 
- 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
 
             
           
             
                         
             
            
评论区