浮躁是人生最大的敌人

Python学习之路——装饰器

Posted on 2019-04-09 21:04  King'home  阅读(115)  评论(0编辑  收藏  举报

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

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

装饰器

# 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数
# 被装饰的函数: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("原有功能")
View Code

有参有返的函数被装饰

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)

 

Copyright © 2024 King'home
Powered by .NET 9.0 on Kubernetes