初识装饰器

装饰器

开放封闭原则

1、开放:对扩展是开放的
2、封闭:对修改是封闭的
(不能修改被装饰的函数的源代码)
(不能修改被装饰的函数的调用方式)

实现装饰器知识储备

1、函数既"变量"
2、高阶函数
a.把一个函数名当做实参传给另一个函数
b.返回值中包含函数名
3、嵌套函数
高阶函数+嵌套函数 —> 装饰器
4、语法糖
@timmer ----> func = timmer(func)

python的内存回收机制

当没有变量在引用内存中的内存地址时,这个内存地址才会释放

高阶函数

a、把一个函数名当做实参传给另一个函数

# 代码一
import time
def func():
    time.sleep(1)
    print('in  the func')
def timmer(f):
    start = time.time()
    f()
    end = time.time()
    print('the func run time is %s' %(end-start))
timmer(func) 

代码一:对于装饰器来说调用方式发生了而改变

b、返回值中包含函数名

# 代码二
import time
def func():
    time.sleep(1)
    print('in  the func')
def timmer(f):
    print('新功能')
    return f
func = timmer(func)
func()

代码二:利用return返回原代码的函数名的特性,先执行新代码,在执行原代码

装饰器(高阶函数+嵌套函数 —> 装饰器)

# 代码三
import time
def inner(f):
    def timmer():
        start = time.time()
        f()
        end = time.time()
        print('the func run time is %s' %(end-start))
    return timmer
@inner # func = inner(func)
def func():
    time.sleep(1)
    print('in the func')
func()

代码三:熟悉程序运行原理,熟悉闭包函数的好处。不修改原来的函数,增加新的功能。

a、被装饰的函数携带参数

# 代码四
import time
def timmer(f):
    def inner(*args, **kwargs):
        start = time.time()
        f(*args, **kwargs)
        end = time.time()
        print(end - start)
    return inner
@timmer
def func1():
    time.sleep(1)
    print('func1')

@timmer
def func2(a):
    time.sleep(1)
    print('func2', a)

func1()
func2(2)

b、被装饰的函数携带返回值

# 代码五
import time
def timmer(f):
    def inner(*args, **kwargs):
        start = time.time()
        ret = f(*args, **kwargs)  # 接收源代码的返回值
        end = time.time()
        print(end - start)
        return ret  # 将接收源代码返回值的变量在返回给装饰后的函数
    return inner
@timmer
def func1():
    time.sleep(1)
    print('func1')
    return '返回值func1'  # 源代码携带返回值
@timmer
def func2(a):
    time.sleep(1)
    print('func2', a)

print(func1())  # 打印源代码中的返回值
func2(2)

c、装饰器携带参数

# 代码六
user,passwd = 'lsc','123'
def auth(auth_type):
    def wrapper(*args, **kwargs):
        print("wrapper func args:", *args, **kwargs)
        username = input("Username:").strip()
        password = input("Password:").strip()
        if user == username and passwd == password:
            print("\033[32;1mUser has passed authentication\033[0m")
            res = home(*args, **kwargs)
            print("---after authenticaion ")
            return res
        else:
            exit("\033[31;1mInvalid username or password\033[0m")
    return wrapper
@auth
def home():
    print("welcome to home  page")
    return "from home"
print(home())
# 代码七
user,passwd = 'lsc','123'
def auth(auth_type):
    print("auth func:",auth_type)
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            print("wrapper func args:", *args, **kwargs)
            username = input("Username:").strip()
            password = input("Password:").strip()
            if user == username and passwd == password:
                print("\033[32;1mUser has passed authentication\033[0m")
                res = func(*args, **kwargs)
                print("---after authenticaion ")
                return res
            else:
                exit("\033[31;1mInvalid username or password\033[0m")
        return wrapper
    return outer_wrapper
@auth(auth_type="local") # 先执行
def home():
    print("welcome to home  page")
    return "from home"
print(home()) #wrapper()

总结:将代码六和代码七对比,发现当装饰器带参数的时候,第一个嵌套函数带入的是装饰器的参数,第二个嵌套函数带入的才是被装饰的函数,可以说是整体下移一位。

from functools import wraps
user,passwd = 'lsc','123'
def auth(auth_type):
    @wraps(auth_type)  # 添加这个函数,打印函数的名字依然是源代码的函数名
    def wrapper(*args, **kwargs):
        print("wrapper func args:", *args, **kwargs)
        username = input("Username:").strip()
        password = input("Password:").strip()
        if user == username and passwd == password:
            print("\033[32;1mUser has passed authentication\033[0m")
            res = home(*args, **kwargs)
            print("---after authenticaion ")
            return res
        else:
            exit("\033[31;1mInvalid username or password\033[0m")
    return wrapper
@auth 
def home():
    print("welcome to home  page")
    return "from home"
print(home.__name__)

猜你喜欢

转载自blog.csdn.net/weixin_42484709/article/details/85112458
今日推荐