zoukankan      html  css  js  c++  java
  • 函数装饰器

    装饰器:闭包的一种应用

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

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

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

    开放封闭式原则:

    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
  • 相关阅读:
    如何进行shell脚本正确性测试
    linux 重命名文件和文件夹
    linux 下 `dirname $0`
    五句话搞定JavaScript作用域
    Javascrpt
    css
    HTML
    python之sqlalchemy
    Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy
    Python之路【第八篇】:堡垒机实例以及数据库操作
  • 原文地址:https://www.cnblogs.com/wangtenghui/p/10645951.html
Copyright © 2011-2022 走看看