函数装饰器

装饰器:闭包的一种应用

名字上来看,就是用来装饰的东西 从

使用上来看,用来‘装饰’其他函数的函数,可以在原先函数功能基础上添加新的功能

装饰器具有一个开放封闭式原则

开放封闭式原则:

1.不能修改被装饰对象(函数)的源代码(封闭)

2.不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果(开放)

开放封闭式原则案例

1.0版本
def fn():
    print('fn run')
fn()
2.0版本
def fn():
    print('fn run0')
    print('fn run1')
    print('fn run2')
fn()

修改了源代码,没有更改调用方式,对外调用方式还是原来的,但功能要有所增加(开放)
def fn():
    print('fn run0')
    print('fn run')
    print('fn run2')
fn()

更改了调用方式,没有修改原功能代码(封闭)
def wrap(fn):
    print('fn run0')
    fn()
    print('fn run2')
wrap(fn)

装饰器:
把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个代替版函数
被装饰的函数:fn()
外层函数:outer(func) outer(fn)==>>func=fn
代替版函数:return inner: 原功能+新功能

被装饰的函数
def fn():
    print('原功能')
# 装饰器
def outer(func):
    def inner():
        func()   # 原有的fn
        print('新功能')
    return inner   #拓展功能后的fn
fn=outer(fn)    # 将拓展功能后的功能函数重新赋值给vase
fn()    # 功能拓展了,且调用方式不变

案例1

def vase():
    print('插花')
def warp(tag):
    def fn():
        tag()
        print('绘画')
    return fn
vase=warp(vase)
vase()

装饰器简化语法

总结:一个函数可以被任意一个相关装饰器装饰,也可以被任意几个装饰器装饰
注:装饰的顺序会影响新增功能的执行顺序

def outer(f):
    def inner():
        f()
        print('绘画')
    return inner
def wrap(f):
    def inner():
        f()
        print('摆放')
    return inner

@outer# 语法糖 | 笑笑语法
@wrap# 语法糖 | 笑笑语法
fn=outer(fn)===>@outer
def fn():
    print('插花')
fn()

有参有返的函数被装饰

增加一个账号处理功能:3位及以上英文字符或汉字
def check_use(fn):
    def inner(use,pwd):
        if not(len(use)>=3 and use.isalpha()):
            print('账号验证失败')
            return False
        result = fn(use,pwd)
        return result
    return inner
@check_use
增加一个密码处理功能:6位及以上英文和数字
def check_pwd(fn):
    def inner(use,pwd):
        if not (len(pw))>=6 and pwd.isalnum():
            print('密码验证失败')
            return False
        result = fn(use,pwd)
        return result
    return inner
@check_use
@check_pwd
登录功能
def login(use,pwd):
    if use =='abc' and pwd=='123qwe':
        print('登入成功')
        return True
    print('登入失败')
    return False

res=login('abc','123qwe')
print(res)

装饰器结合可变长参数

def wrap(fn):
    def inner(*args, **kwargs):
        # print(args)
        # print(kwargs)
        result = fn(*args, **kwargs)
        print('新增功能')
        return result

    # return inner


@wrap
def func(a, b, c, *, x, y, z):
    print(a, b, c, x, y, z)
    print('原有功能')


func(1, 2, 3, x=10, y=20, z=30)

登入案例

is_login = False  # 登录状态

def login():
    global is_login
    usr = input('usr: ')
    if not (len(usr) >= 3 and usr.isalpha()):
        print('账号验证失败')
        return False
    pwd = input('pwd: ')
    if usr == 'abc' and pwd =='123qwe':
        print('登录成功')
        is_login = True
    else:
        print('登录失败')
        is_login = False


# 完成一个登录状态校验的装饰器
def check_login(fn):
    def inner(*args, **kwargs):
        # 查看个人主页或销售功能前:如果没有登录先登录,反之可以进入其功能
        if is_login != True:
            print('你未登录')
            login()
        # 查看个人主页或销售
        result = fn(*args, **kwargs)
        return result
    return inner

# 查看个人主页功能
@check_login
def home():
    print('个人主页')

# 销售功能
@check_login
def sell():
    print('可以销售')

home()
View Code
原文地址:https://www.cnblogs.com/wangtenghui/p/10645951.html