装饰器

Posted limengda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰器相关的知识,希望对你有一定的参考价值。

nonlocal关键字

# 作用:将 L 与 E(E中的名字需要提前定义) 的名字统一

# 应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值

# 案例:

def outer():
    num = 10
    print(num)  # 10 
    def inner():
        nonlocal num
        num = 20
        p77rint(num)  # 20
    inner()
    print(num)  # 20

开放封闭原则:不改变调用方式与源代码上增加功能

'''
1.不能修改被装饰对象(函数)的源代码(封闭)
2.不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果(开放)
'''

装饰器

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

def fn():
    print("原有功能")

# 装饰器
def outer(tag):
    def inner():
        tag()
        print(新增功能")
    return inner
fn = outer(fn)              
              
fn()

@语法糖: @外层函数

def outer(f):
    def inner():
        f()
        print("新增功能1")
    return inner
              
def wrap(f):
    def inner():
        f()
        print("新增功能2")
    return inner              

@wrap  # 被装饰的顺序决定了新增功能的执行顺序
@outer  # <==> fn = outer(fn): inner      
def fn():
    print("原有功能")

有参有返的函数被装饰

def check_usr(fn):  # fn, login, inner:不同状态下的login,所以参数是统一的
    def inner(usr, pwd):
        # 在原功能上添加新功能
        if not (len(usr) >= 3 and usr.isalpha()):
            print('账号验证失败')
            return False
        
        # 原有功能
        result = fn(usr, pwd)
        
        # 在原功能下添加新功能
        # ...
        
        return result
    return inner


@check_usr
def login(usr, pwd):
    if usr == 'abc' and pwd =='123qwe':
        print('登录成功')
        return True
    print('登录失败')
    return False

# 总结:
# 1.login有参数,所以inner与fn都有相同参数
# 2.login有返回值,所以inner与fn都有返回值

"""
inner(usr, pwd):
    res = fn(usr, pwd)  # 原login的返回值
    return res


login = check_usr(login) = inner

res = login('abc', '123qwe')  # inner的返回值
"""

装饰器最终写法


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

@wrap
def fn1():
    print('fn1的原有功能')
@wrap
def fn2(a, b):
    print('fn2的原有功能')
@wrap   
def fn3():
    print('fn3的原有功能')
    return True
@wrap
def fn4(a, *, x):
    print('fn4的原有功能')
    return True

fn1()
fn2(10, 20)
fn3()
fn4(10, x=20)

带参装饰器:了解

# 了解
def outer(input_color):
    def wrap(fn):
        if input_color == 'red':
            info = '\033[36;41mnew action\33[0m'
        else:
            info = 'yellow:new action'

        def inner(*args, **kwargs):
            pass
            result = fn(*args, **kwargs)
            print(info)
            return result
        return inner
    return wrap  # outer(color) => wrap


color = input('color: ')
@outer(color)  # @outer(color) ==> @wrap  # func => inner
def func():
    print('func run')

func()

登录认证功能

is_login = False  # 登录状态

def 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()

以上是关于装饰器的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象学习之八,装饰器

thymeleaf 片段渲染后重新加载 javascript

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码